diff --git a/.dockerignore b/.dockerignore
index 59a09431..2fc1cbae 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,2 +1,3 @@
.github/
.python-version
+/node_modules/
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index 6f954521..8da10e9f 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -14,11 +14,11 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: run unit test using postgres
- run: docker-compose run ibet-prime-postgres
+ run: docker compose run ibet-prime-postgres
migration-test-postgres:
name: 'Migration tests (PostgreSQL)'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: run unit test using postgres
- run: docker-compose run ibet-prime-postgres bash --login -c "cd /app/ibet-Prime && pytest -vv --test-alembic -m 'alembic'"
+ run: docker compose run ibet-prime-postgres bash --login -c "cd /app/ibet-Prime && pytest -vv --test-alembic -m 'alembic'"
diff --git a/.gitignore b/.gitignore
index ee20fe18..254f4880 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,9 @@ __pycache__/
# pyenv
.python-version
+# Node
+node_modules/
+
# Intellij
.idea
/*.iml
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index b01cb4fa..08fe14c4 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/psf/black
- rev: 24.1.1
+ rev: 24.4.2
hooks:
- id: black
- language_version: python3.11
+ language_version: python3.12
diff --git a/Dockerfile b/Dockerfile
index b9fb483e..11cc55d0 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -52,15 +52,16 @@ RUN echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~apl/.bash_profile \
# install python
USER apl
RUN . ~/.bash_profile \
- && pyenv install 3.11.2 \
- && pyenv global 3.11.2 \
+ && pyenv install 3.12.2 \
+ && pyenv global 3.12.2 \
&& pip install --upgrade pip setuptools
# install poetry
RUN . ~/.bash_profile \
- && python -m pip install poetry==1.7.1
+ && python -m pip install poetry==1.8.2
RUN . ~/.bash_profile \
- && poetry config virtualenvs.create false
+ && poetry config virtualenvs.create false \
+ && poetry config installer.max-workers 1
# install python packages
USER root
@@ -88,10 +89,10 @@ COPY pyproject.toml /app/ibet-Prime/pyproject.toml
COPY poetry.lock /app/ibet-Prime/poetry.lock
RUN . ~/.bash_profile \
&& cd /app/ibet-Prime \
- && poetry install --only main --no-root -E ibet-explorer \
+ && poetry install --only main --no-root --all-extras \
&& rm -f /app/ibet-Prime/pyproject.toml \
&& rm -f /app/ibet-Prime/poetry.lock
-ENV PYTHONPATH /app/ibet-Prime
+ENV PYTHONPATH /app/ibet-Prime:/app/ibet-Prime/cmd
# command deploy
USER apl
diff --git a/Makefile b/Makefile
index 1bff99f8..5e623c90 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
-.PHONY: isort black test run
+.PHONY: format isort black doc test test_migrations run
install:
- poetry install --no-root -E ibet-explorer
+ poetry install --no-root --all-extras
poetry run pre-commit install
update:
@@ -15,6 +15,9 @@ isort:
black:
black .
+doc:
+ poetry run python docs/generate_openapi_doc.py
+
test:
pytest tests/
diff --git a/README.md b/README.md
index 662d0fcf..ea624c1e 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
# ibet-Prime
-
+
@@ -22,11 +22,11 @@ English | [日本語](./README_JA.md)
## Dependencies
-- [Python3](https://www.python.org/downloads/release/python-3811/) - version 3.11
+- [Python3](https://www.python.org/downloads/release/python-3811/) - version 3.12
- [PostgreSQL](https://www.postgresql.org/) - version 15
- [GoQuorum](https://github.com/ConsenSys/quorum)
- We support the official GoQuorum node of [ibet-Network](https://github.com/BoostryJP/ibet-Network).
- - We use [ganache](https://github.com/trufflesuite/ganache) for local development and unit testing, and we use the latest version.
+ - We use [hardhat network](https://hardhat.org/hardhat-network/) for local development and unit testing, and we use the latest version.
## Supported ibet smart contract version
@@ -52,7 +52,7 @@ English | [日本語](./README_JA.md)
Install python packages with:
```bash
-$ poetry install --no-root --only main -E ibet-explorer
+$ poetry install --no-root --only main --all-extras
```
### Install pre-commit hook
@@ -60,6 +60,11 @@ $ poetry install --no-root --only main -E ibet-explorer
$ poetry run pre-commit install
```
+### Install hardhat
+```bash
+$ npm install
+```
+
### Setting environment variables
The main environment variables are as follows.
diff --git a/README_JA.md b/README_JA.md
index 8a692a1b..8cdb2d86 100644
--- a/README_JA.md
+++ b/README_JA.md
@@ -5,7 +5,7 @@
# ibet-Prime
-
+
@@ -23,11 +23,11 @@
## 依存
-- [Python3](https://www.python.org/downloads/release/python-3811/) - バージョン 3.11
+- [Python3](https://www.python.org/downloads/release/python-3811/) - バージョン 3.12
- [PostgreSQL](https://www.postgresql.org/) - バージョン 15
- [GoQuorum](https://github.com/ConsenSys/quorum)
- [ibet-Network](https://github.com/BoostryJP/ibet-Network) の公式の GoQuorum をサポートしています。
- - 最新の [ganache](https://github.com/trufflesuite/ganache) (ganache-cli) をローカル開発およびユニットテストで利用しています。
+ - 最新の [hardhat network](https://hardhat.org/hardhat-network/) をローカル開発およびユニットテストで利用しています。
## コントラクトのバージョン
@@ -53,7 +53,7 @@
以下のコマンドで Python パッケージをインストールします。
```bash
-$ poetry install --no-root --only main -E ibet-explorer
+$ poetry install --no-root --only main --all-extras
```
### pre-commit hookのインストール
@@ -61,6 +61,11 @@ $ poetry install --no-root --only main -E ibet-explorer
$ poetry run pre-commit install
```
+### hardhatのインストール
+```bash
+$ npm install
+```
+
### 環境変数の設定
主要な環境変数は以下の通りです。
diff --git a/app/exceptions.py b/app/exceptions.py
index 158ed82c..9db334fb 100644
--- a/app/exceptions.py
+++ b/app/exceptions.py
@@ -56,6 +56,15 @@ class Integer64bitLimitExceededError(AppError):
code = 5
+class OperationNotSupportedVersionError(AppError):
+ """
+ The token version for which the operation is not supported
+ """
+
+ status_code = status.HTTP_400_BAD_REQUEST
+ code = 6
+
+
class OperationNotAllowedStateError(AppError):
"""
Error returned when server-side data is not ready to process the request
diff --git a/app/log.py b/app/log.py
index fffd1528..b5b66281 100644
--- a/app/log.py
+++ b/app/log.py
@@ -20,7 +20,7 @@
import logging
import sys
import urllib
-from datetime import datetime
+from datetime import UTC, datetime
from fastapi import Request, Response
@@ -34,6 +34,9 @@
ACCESS_LOG = logging.getLogger("issuer_api_access")
ACCESS_LOG.propagate = False
+logging.getLogger("web3.manager.RequestManager").propagate = False
+logging.getLogger("web3.manager.RequestManager").addHandler(logging.NullHandler())
+
INFO_FORMAT = "[%(asctime)s] {}[%(process)d] [%(levelname)s] %(message)s"
DEBUG_FORMAT = "[%(asctime)s] {}[%(process)d] [%(levelname)s] %(message)s [in %(pathname)s:%(lineno)d]"
TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S %z"
@@ -108,7 +111,9 @@ def output_access_log(req: Request, res: Response, request_start_time: datetime)
method = req.scope.get("method", "")
http_version = req.scope.get("http_version", "")
status_code = res.status_code
- response_time = (datetime.utcnow() - request_start_time).total_seconds()
+ response_time = (
+ datetime.now(UTC).replace(tzinfo=None) - request_start_time
+ ).total_seconds()
access_msg = ACCESS_FORMAT % (
method,
url,
diff --git a/app/main.py b/app/main.py
index 0a64e74f..55167cfd 100644
--- a/app/main.py
+++ b/app/main.py
@@ -17,7 +17,7 @@
SPDX-License-Identifier: Apache-2.0
"""
-from datetime import datetime
+from datetime import UTC, datetime
from fastapi import FastAPI, Request
from fastapi.encoders import jsonable_encoder
@@ -40,6 +40,7 @@
ledger,
notification,
position,
+ settlement,
share,
token_holders,
)
@@ -62,7 +63,7 @@
app = FastAPI(
title="ibet Prime",
description="Security token management system for ibet network",
- version="24.3.0",
+ version="24.6",
contact={"email": "dev@boostry.co.jp"},
license_info={
"name": "Apache 2.0",
@@ -74,7 +75,7 @@
@app.middleware("http")
async def api_call_handler(request: Request, call_next):
- request_start_time = datetime.utcnow()
+ request_start_time = datetime.now(UTC).replace(tzinfo=None)
response = await call_next(request)
output_access_log(request, response, request_start_time)
return response
@@ -105,6 +106,7 @@ async def root():
app.include_router(token_holders.router)
app.include_router(bc_explorer.router)
app.include_router(freeze_log.router)
+app.include_router(settlement.router)
###############################################################
@@ -206,7 +208,7 @@ async def response_limit_exceeded_error_handler(
)
-# 400:ResponseLimitExceededError
+# 400:Integer64bitLimitExceededError
@app.exception_handler(Integer64bitLimitExceededError)
async def response_limit_exceeded_error_handler(
request: Request, exc: Integer64bitLimitExceededError
@@ -218,6 +220,18 @@ async def response_limit_exceeded_error_handler(
)
+# 400:OperationNotSupportedVersionError
+@app.exception_handler(OperationNotSupportedVersionError)
+async def operation_not_supported_version_error_handler(
+ request: Request, exc: OperationNotSupportedVersionError
+):
+ meta = {"code": 6, "title": "OperationNotSupportedVersionError"}
+ return JSONResponse(
+ status_code=exc.status_code,
+ content=jsonable_encoder({"meta": meta, "detail": exc.args[0]}),
+ )
+
+
# 400:OperationNotAllowedStateError
@app.exception_handler(OperationNotAllowedStateError)
async def operation_not_permitted_error_handler(
diff --git a/app/model/__init__.py b/app/model/__init__.py
index f8bf1b6e..3684b4dd 100644
--- a/app/model/__init__.py
+++ b/app/model/__init__.py
@@ -17,6 +17,7 @@
SPDX-License-Identifier: Apache-2.0
"""
+from datetime import datetime
from typing import Annotated, Any
from pydantic import WrapValidator
@@ -37,3 +38,28 @@ def ethereum_address_validator(
EthereumAddress = Annotated[str, WrapValidator(ethereum_address_validator)]
+
+
+def datetime_string_validator(
+ value: Any, handler: ValidatorFunctionWrapHandler, *args, **kwargs
+):
+ """Validate string datetime format
+
+ - %Y/%m/%d %H:%M:%S
+ """
+ if value is not None:
+ datetime_format = "%Y-%m-%d %H:%M:%S"
+
+ if not isinstance(value, str):
+ raise ValueError(f"value must be of string datetime format")
+
+ try:
+ converted = datetime.strptime(value, datetime_format)
+ if value != converted.strftime(datetime_format):
+ raise ValueError(f"value must be string datetime format")
+ except ValueError:
+ raise ValueError(f"value must be of string datetime format")
+ return value
+
+
+ValidatedDatetimeStr = Annotated[str, WrapValidator(datetime_string_validator)]
diff --git a/app/model/blockchain/__init__.py b/app/model/blockchain/__init__.py
index 118c01e2..4dc0dd3f 100644
--- a/app/model/blockchain/__init__.py
+++ b/app/model/blockchain/__init__.py
@@ -20,7 +20,7 @@
from .e2e_messaging import E2EMessaging
from .exchange import IbetExchangeInterface, IbetSecurityTokenEscrow
from .freeze_log import FreezeLogContract
-from .personal_info import PersonalInfoContract
+from .personal_info import ContractPersonalInfoType, PersonalInfoContract
from .token import (
IbetSecurityTokenInterface,
IbetShareContract,
diff --git a/app/model/blockchain/exchange.py b/app/model/blockchain/exchange.py
index 385c2778..981d41b9 100644
--- a/app/model/blockchain/exchange.py
+++ b/app/model/blockchain/exchange.py
@@ -20,6 +20,12 @@
from web3.exceptions import TimeExhausted
from app.exceptions import ContractRevertError, SendTransactionError
+from app.model.blockchain.tx_params.ibet_security_token_dvp import (
+ AbortDeliveryParams,
+ CancelDeliveryParams,
+ CreateDeliveryParams,
+ FinishDeliveryParams,
+)
from app.model.blockchain.tx_params.ibet_security_token_escrow import (
ApproveTransferParams,
)
@@ -99,3 +105,120 @@ async def approve_transfer(
raise SendTransactionError(timeout_error)
except Exception as err:
raise SendTransactionError(err)
+
+
+class IbetSecurityTokenDVP(IbetExchangeInterface):
+ """IbetSecurityTokenDVP contract"""
+
+ def __init__(self, contract_address: str):
+ super().__init__(
+ contract_address=contract_address, contract_name="IbetSecurityTokenDVP"
+ )
+
+ async def create_delivery(
+ self, data: CreateDeliveryParams, tx_from: str, private_key: bytes
+ ):
+ """Create Delivery"""
+ try:
+ tx = await self.exchange_contract.functions.createDelivery(
+ data.token_address,
+ data.buyer_address,
+ data.amount,
+ data.agent_address,
+ data.data,
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": tx_from,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ tx_hash, tx_receipt = await AsyncContractUtils.send_transaction(
+ transaction=tx, private_key=private_key
+ )
+ return tx_hash, tx_receipt
+ except ContractRevertError:
+ raise
+ except TimeExhausted as timeout_error:
+ raise SendTransactionError(timeout_error)
+ except Exception as err:
+ raise SendTransactionError(err)
+
+ async def cancel_delivery(
+ self, data: CancelDeliveryParams, tx_from: str, private_key: bytes
+ ):
+ """Cancel Delivery"""
+ try:
+ tx = await self.exchange_contract.functions.cancelDelivery(
+ data.delivery_id
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": tx_from,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ tx_hash, tx_receipt = await AsyncContractUtils.send_transaction(
+ transaction=tx, private_key=private_key
+ )
+ return tx_hash, tx_receipt
+ except ContractRevertError:
+ raise
+ except TimeExhausted as timeout_error:
+ raise SendTransactionError(timeout_error)
+ except Exception as err:
+ raise SendTransactionError(err)
+
+ async def finish_delivery(
+ self, data: FinishDeliveryParams, tx_from: str, private_key: bytes
+ ):
+ """Finish Delivery"""
+ try:
+ tx = await self.exchange_contract.functions.finishDelivery(
+ data.delivery_id
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": tx_from,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ tx_hash, tx_receipt = await AsyncContractUtils.send_transaction(
+ transaction=tx, private_key=private_key
+ )
+ return tx_hash, tx_receipt
+ except ContractRevertError:
+ raise
+ except TimeExhausted as timeout_error:
+ raise SendTransactionError(timeout_error)
+ except Exception as err:
+ raise SendTransactionError(err)
+
+ async def abort_delivery(
+ self, data: AbortDeliveryParams, tx_from: str, private_key: bytes
+ ):
+ """Abort Delivery"""
+ try:
+ tx = await self.exchange_contract.functions.abortDelivery(
+ data.delivery_id
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": tx_from,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ tx_hash, tx_receipt = await AsyncContractUtils.send_transaction(
+ transaction=tx, private_key=private_key
+ )
+ return tx_hash, tx_receipt
+ except ContractRevertError:
+ raise
+ except TimeExhausted as timeout_error:
+ raise SendTransactionError(timeout_error)
+ except Exception as err:
+ raise SendTransactionError(err)
diff --git a/app/model/blockchain/personal_info.py b/app/model/blockchain/personal_info.py
index e1c02306..639fed49 100644
--- a/app/model/blockchain/personal_info.py
+++ b/app/model/blockchain/personal_info.py
@@ -24,6 +24,7 @@
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
from eth_keyfile import decode_keyfile_json
+from pydantic import BaseModel
from web3.contract import AsyncContract
from web3.exceptions import TimeExhausted
@@ -37,6 +38,17 @@
web3 = Web3Wrapper()
+class ContractPersonalInfoType(BaseModel):
+ key_manager: str | None = None
+ name: str | None = None
+ address: str | None = None
+ postal_code: str | None = None
+ email: str | None = None
+ birth: str | None = None
+ is_corporate: bool | None = None
+ tax_category: int | None = None
+
+
class PersonalInfoContract:
"""PersonalInfo contract"""
@@ -48,27 +60,16 @@ def __init__(self, issuer: Account, contract_address=None):
contract_name="PersonalInfo", contract_address=contract_address
)
self.issuer = issuer
+ self.cipher = None
async def get_info(self, account_address: str, default_value=None):
- """Get personal information
+ """Get personal information from contract storage
:param account_address: Token holder account address
:param default_value: Default value for items for which no value is set. (If not specified: None)
:return: Personal info
"""
- # Set default value
- personal_info = {
- "key_manager": default_value,
- "name": default_value,
- "postal_code": default_value,
- "address": default_value,
- "email": default_value,
- "birth": default_value,
- "is_corporate": default_value,
- "tax_category": default_value,
- }
-
# Get encrypted personal information
personal_info_state = await AsyncContractUtils.call_function(
contract=self.personal_info_contract,
@@ -82,18 +83,32 @@ async def get_info(self, account_address: str, default_value=None):
encrypted_info = personal_info_state[2]
if encrypted_info == "":
- return personal_info # default
+ return ContractPersonalInfoType(
+ key_manager=default_value,
+ name=default_value,
+ address=default_value,
+ postal_code=default_value,
+ email=default_value,
+ birth=default_value,
+ ).model_dump()
else:
# Get issuer's RSA private key
try:
- passphrase = E2EEUtils.decrypt(self.issuer.rsa_passphrase)
- key = RSA.importKey(self.issuer.rsa_private_key, passphrase)
- cipher = PKCS1_OAEP.new(key)
+ if self.cipher is None:
+ passphrase = E2EEUtils.decrypt(self.issuer.rsa_passphrase)
+ key = RSA.importKey(self.issuer.rsa_private_key, passphrase)
+ self.cipher = PKCS1_OAEP.new(key)
except Exception as err:
logging.error(f"Cannot open the private key: {err}")
- return personal_info # default
-
- if cipher is not None:
+ return ContractPersonalInfoType(
+ key_manager=default_value,
+ name=default_value,
+ address=default_value,
+ postal_code=default_value,
+ email=default_value,
+ birth=default_value,
+ ).model_dump()
+ if self.cipher is not None:
try:
ciphertext = base64.decodebytes(encrypted_info.encode("utf-8"))
# NOTE:
@@ -104,30 +119,28 @@ async def get_info(self, account_address: str, default_value=None):
if len(ciphertext) == 1279:
hex_fixed = "00" + ciphertext.hex()
ciphertext = base64.b16decode(hex_fixed.upper())
- decrypted_info = json.loads(cipher.decrypt(ciphertext))
-
- personal_info["key_manager"] = decrypted_info.get(
- "key_manager", default_value
- )
- personal_info["name"] = decrypted_info.get("name", default_value)
- personal_info["address"] = decrypted_info.get(
- "address", default_value
- )
- personal_info["postal_code"] = decrypted_info.get(
- "postal_code", default_value
- )
- personal_info["email"] = decrypted_info.get("email", default_value)
- personal_info["birth"] = decrypted_info.get("birth", default_value)
- personal_info["is_corporate"] = decrypted_info.get(
- "is_corporate", default_value
- )
- personal_info["tax_category"] = decrypted_info.get(
- "tax_category", default_value
- )
- return personal_info
+ decrypted_info = json.loads(self.cipher.decrypt(ciphertext))
+
+ return ContractPersonalInfoType(
+ key_manager=decrypted_info.get("key_manager", default_value),
+ name=decrypted_info.get("name", default_value),
+ address=decrypted_info.get("address", default_value),
+ postal_code=decrypted_info.get("postal_code", default_value),
+ email=decrypted_info.get("email", default_value),
+ birth=decrypted_info.get("birth", default_value),
+ is_corporate=decrypted_info.get("is_corporate", None),
+ tax_category=decrypted_info.get("tax_category", None),
+ ).model_dump()
except Exception as err:
logging.error(f"Failed to decrypt: {err}")
- return personal_info # default
+ return ContractPersonalInfoType(
+ key_manager=default_value,
+ name=default_value,
+ address=default_value,
+ postal_code=default_value,
+ email=default_value,
+ birth=default_value,
+ ).model_dump()
async def register_info(
self, account_address: str, data: dict, default_value=None
diff --git a/app/model/blockchain/token.py b/app/model/blockchain/token.py
index 8b1c8952..559ae250 100644
--- a/app/model/blockchain/token.py
+++ b/app/model/blockchain/token.py
@@ -18,7 +18,7 @@
"""
import json
-from datetime import datetime, timedelta
+from datetime import UTC, datetime, timedelta
from decimal import Decimal
from random import randint
from typing import List, TypeVar
@@ -113,15 +113,17 @@ async def check_attr_update(
async def record_attr_update(self, db_session: AsyncSession):
_token_attr_update = TokenAttrUpdate()
_token_attr_update.token_address = self.token_address
- _token_attr_update.updated_datetime = datetime.utcnow()
+ _token_attr_update.updated_datetime = datetime.now(UTC).replace(tzinfo=None)
db_session.add(_token_attr_update)
async def create_cache(self, db_session: AsyncSession):
token_cache = TokenCache()
token_cache.token_address = self.token_address
token_cache.attributes = self.__dict__
- token_cache.cached_datetime = datetime.utcnow()
- token_cache.expiration_datetime = datetime.utcnow() + timedelta(
+ token_cache.cached_datetime = datetime.now(UTC).replace(tzinfo=None)
+ token_cache.expiration_datetime = datetime.now(UTC).replace(
+ tzinfo=None
+ ) + timedelta(
seconds=randint(
TOKEN_CACHE_TTL - TOKEN_CACHE_TTL_JITTER,
TOKEN_CACHE_TTL + TOKEN_CACHE_TTL_JITTER,
@@ -165,6 +167,7 @@ async def get_account_balance(self, account_address: str):
class IbetSecurityTokenInterface(IbetStandardTokenInterface):
personal_info_contract_address: str
+ require_personal_info_registered: bool
transferable: bool
is_offering: bool
transfer_approval_required: bool
@@ -513,7 +516,8 @@ async def get(self):
)
if (
is_updated is False
- and token_cache.expiration_datetime > datetime.utcnow()
+ and token_cache.expiration_datetime
+ > datetime.now(UTC).replace(tzinfo=None)
):
# Get data from cache
for k, v in token_cache.attributes.items():
@@ -550,6 +554,9 @@ async def get(self):
AsyncContractUtils.call_function(
contract, "personalInfoAddress", (), ZERO_ADDRESS
),
+ AsyncContractUtils.call_function(
+ contract, "requirePersonalInfoRegistered", (), True
+ ),
AsyncContractUtils.call_function(
contract, "transferable", (), False
),
@@ -596,6 +603,7 @@ async def get(self):
self.privacy_policy,
self.status,
self.personal_info_contract_address,
+ self.require_personal_info_registered,
self.transferable,
self.is_offering,
self.transfer_approval_required,
@@ -967,6 +975,28 @@ async def update(
except Exception as err:
raise SendTransactionError(err)
+ if data.require_personal_info_registered is not None:
+ tx = await contract.functions.setRequirePersonalInfoRegistered(
+ data.require_personal_info_registered
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": tx_from,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ try:
+ await AsyncContractUtils.send_transaction(
+ transaction=tx, private_key=private_key
+ )
+ except ContractRevertError:
+ raise
+ except TimeExhausted as timeout_error:
+ raise SendTransactionError(timeout_error)
+ except Exception as err:
+ raise SendTransactionError(err)
+
if data.contact_information is not None:
tx = await contract.functions.setContactInformation(
data.contact_information
@@ -1122,7 +1152,8 @@ async def get(self) -> T:
)
if (
is_updated is False
- and token_cache.expiration_datetime > datetime.utcnow()
+ and token_cache.expiration_datetime
+ > datetime.now(UTC).replace(tzinfo=None)
):
# Get data from cache
for k, v in token_cache.attributes.items():
@@ -1159,6 +1190,9 @@ async def get(self) -> T:
AsyncContractUtils.call_function(
contract, "personalInfoAddress", (), ZERO_ADDRESS
),
+ AsyncContractUtils.call_function(
+ contract, "requirePersonalInfoRegistered", (), True
+ ),
AsyncContractUtils.call_function(
contract, "transferable", (), False
),
@@ -1189,6 +1223,7 @@ async def get(self) -> T:
self.privacy_policy,
self.status,
self.personal_info_contract_address,
+ self.require_personal_info_registered,
self.transferable,
self.is_offering,
self.transfer_approval_required,
@@ -1272,6 +1307,28 @@ async def update(
except Exception as err:
raise SendTransactionError(err)
+ if data.require_personal_info_registered is not None:
+ tx = await contract.functions.setRequirePersonalInfoRegistered(
+ data.require_personal_info_registered
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": tx_from,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ try:
+ await AsyncContractUtils.send_transaction(
+ transaction=tx, private_key=private_key
+ )
+ except ContractRevertError:
+ raise
+ except TimeExhausted as timeout_error:
+ raise SendTransactionError(timeout_error)
+ except Exception as err:
+ raise SendTransactionError(err)
+
if data.dividends is not None:
_dividends = int(Decimal(str(data.dividends)) * Decimal("10000000000000"))
tx = await contract.functions.setDividendInformation(
diff --git a/app/model/blockchain/tx_params/ibet_security_token_dvp.py b/app/model/blockchain/tx_params/ibet_security_token_dvp.py
new file mode 100644
index 00000000..de05f1ed
--- /dev/null
+++ b/app/model/blockchain/tx_params/ibet_security_token_dvp.py
@@ -0,0 +1,40 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+from pydantic import BaseModel
+
+
+class CreateDeliveryParams(BaseModel):
+ token_address: str
+ buyer_address: str
+ amount: int
+ agent_address: str
+ data: str
+
+
+class CancelDeliveryParams(BaseModel):
+ delivery_id: int
+
+
+class FinishDeliveryParams(BaseModel):
+ delivery_id: int
+
+
+class AbortDeliveryParams(BaseModel):
+ delivery_id: int
diff --git a/app/model/blockchain/tx_params/ibet_share.py b/app/model/blockchain/tx_params/ibet_share.py
index 3edcd27d..71dc0524 100644
--- a/app/model/blockchain/tx_params/ibet_share.py
+++ b/app/model/blockchain/tx_params/ibet_share.py
@@ -44,6 +44,7 @@ class UpdateParams(BaseModel):
dividends: Optional[float] = None
tradable_exchange_contract_address: Optional[EthereumAddress] = None
personal_info_contract_address: Optional[EthereumAddress] = None
+ require_personal_info_registered: Optional[bool] = None
transferable: Optional[bool] = None
status: Optional[bool] = None
is_offering: Optional[bool] = None
diff --git a/app/model/blockchain/tx_params/ibet_straight_bond.py b/app/model/blockchain/tx_params/ibet_straight_bond.py
index 6dd23437..28b734c9 100644
--- a/app/model/blockchain/tx_params/ibet_straight_bond.py
+++ b/app/model/blockchain/tx_params/ibet_straight_bond.py
@@ -52,6 +52,7 @@ class UpdateParams(BaseModel):
is_redeemed: Optional[bool] = None
tradable_exchange_contract_address: Optional[EthereumAddress] = None
personal_info_contract_address: Optional[EthereumAddress] = None
+ require_personal_info_registered: Optional[bool] = None
contact_information: Optional[str] = None
privacy_policy: Optional[str] = None
transfer_approval_required: Optional[bool] = None
diff --git a/app/model/db/__init__.py b/app/model/db/__init__.py
index cc4b0fe9..46b55f8a 100644
--- a/app/model/db/__init__.py
+++ b/app/model/db/__init__.py
@@ -31,9 +31,11 @@
BatchRegisterPersonalInfoUploadStatus,
)
from .bulk_transfer import BulkTransfer, BulkTransferUpload
+from .dvp_agent_account import DVPAgentAccount
from .e2e_messaging_account import E2EMessagingAccount, E2EMessagingAccountRsaKey
from .freeze_log_account import FreezeLogAccount
from .idx_block_data import IDXBlockData, IDXBlockDataBlockNumber
+from .idx_delivery import DeliveryStatus, IDXDelivery, IDXDeliveryBlockNumber
from .idx_e2e_messaging import IDXE2EMessaging, IDXE2EMessagingBlockNumber
from .idx_issue_redeem import (
IDXIssueRedeem,
@@ -42,7 +44,12 @@
IDXIssueRedeemSortItem,
)
from .idx_lock_unlock import IDXLock, IDXUnlock
-from .idx_personal_info import IDXPersonalInfo, IDXPersonalInfoBlockNumber
+from .idx_personal_info import (
+ IDXPersonalInfo,
+ IDXPersonalInfoBlockNumber,
+ IDXPersonalInfoHistory,
+ PersonalInfoEventType,
+)
from .idx_position import (
IDXLockedPosition,
IDXPosition,
diff --git a/app/model/db/auth_token.py b/app/model/db/auth_token.py
index a74d5073..5c69a6f7 100644
--- a/app/model/db/auth_token.py
+++ b/app/model/db/auth_token.py
@@ -22,7 +22,7 @@
from sqlalchemy import DateTime, Integer, String
from sqlalchemy.orm import Mapped, mapped_column
-from .base import Base
+from .base import Base, naive_utcnow
class AuthToken(Base):
@@ -35,9 +35,7 @@ class AuthToken(Base):
# authentication token (sha256 hashed)
auth_token: Mapped[str | None] = mapped_column(String(64))
# usage start
- usage_start: Mapped[datetime | None] = mapped_column(
- DateTime, default=datetime.utcnow
- )
+ usage_start: Mapped[datetime | None] = mapped_column(DateTime, default=naive_utcnow)
# valid duration (sec)
# - 0: endless
valid_duration: Mapped[int | None] = mapped_column(Integer, nullable=False)
diff --git a/app/model/db/base.py b/app/model/db/base.py
index 43b92789..80f95571 100644
--- a/app/model/db/base.py
+++ b/app/model/db/base.py
@@ -18,20 +18,28 @@
"""
import time
-from datetime import date as datetime_date, datetime
+from datetime import UTC, date as datetime_date, datetime
from sqlalchemy import DateTime
-from sqlalchemy.orm import Mapped, declarative_base, mapped_column
+from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from app.database import get_db_schema
-class BaseModel(object):
+def aware_utcnow():
+ return datetime.now(UTC)
+
+
+def naive_utcnow():
+ return aware_utcnow().replace(tzinfo=None)
+
+
+class Base(DeclarativeBase):
# created datetime(UTC)
- created: Mapped[datetime | None] = mapped_column(DateTime, default=datetime.utcnow)
+ created: Mapped[datetime | None] = mapped_column(DateTime, default=naive_utcnow)
# modified datetime(UTC)
modified: Mapped[datetime | None] = mapped_column(
- DateTime, default=datetime.utcnow, onupdate=datetime.utcnow
+ DateTime, default=naive_utcnow, onupdate=naive_utcnow
)
@staticmethod
@@ -42,8 +50,6 @@ def datetime_to_timestamp(date):
return None
-Base = declarative_base(cls=BaseModel)
-
schema = get_db_schema()
if schema is not None:
setattr(Base, "__table_args__", {"schema": schema})
diff --git a/app/model/db/dvp_agent_account.py b/app/model/db/dvp_agent_account.py
new file mode 100644
index 00000000..a0150928
--- /dev/null
+++ b/app/model/db/dvp_agent_account.py
@@ -0,0 +1,38 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+from sqlalchemy import JSON, Boolean, String
+from sqlalchemy.orm import Mapped, mapped_column
+
+from .base import Base
+
+
+class DVPAgentAccount(Base):
+ """Account for DVP payment agent"""
+
+ __tablename__ = "dvp_agent_account"
+
+ # account address
+ account_address: Mapped[str] = mapped_column(String(42), primary_key=True)
+ # ethereum keyfile
+ keyfile: Mapped[dict | None] = mapped_column(JSON)
+ # ethereum account password(encrypted)
+ eoa_password: Mapped[str | None] = mapped_column(String(2000))
+ # delete flag
+ is_deleted: Mapped[bool | None] = mapped_column(Boolean, default=False)
diff --git a/app/model/db/idx_delivery.py b/app/model/db/idx_delivery.py
new file mode 100644
index 00000000..8cec4553
--- /dev/null
+++ b/app/model/db/idx_delivery.py
@@ -0,0 +1,129 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+from datetime import datetime
+from enum import IntEnum
+
+from sqlalchemy import BigInteger, Boolean, DateTime, String, Text
+from sqlalchemy.orm import Mapped, mapped_column
+
+from .base import Base
+
+
+class DeliveryStatus(IntEnum):
+ """DVP Delivery Status"""
+
+ DELIVERY_CREATED = 0
+ DELIVERY_CANCELED = 1
+ DELIVERY_CONFIRMED = 2
+ DELIVERY_FINISHED = 3
+ DELIVERY_ABORTED = 4
+
+
+class IDXDelivery(Base):
+ """DVP Delivery Event (INDEX)"""
+
+ __tablename__ = "idx_delivery"
+
+ # Sequence Id
+ id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
+ # DVP Contract Address
+ exchange_address: Mapped[str] = mapped_column(
+ String(42), index=True, nullable=False
+ )
+ # Delivery ID
+ delivery_id: Mapped[int] = mapped_column(BigInteger, index=True, nullable=False)
+ # Token Address
+ token_address: Mapped[str] = mapped_column(String(42), index=True, nullable=False)
+ # Delivery Buyer
+ buyer_address: Mapped[str] = mapped_column(String(42), nullable=False)
+ # Delivery From
+ seller_address: Mapped[str] = mapped_column(String(42), index=True, nullable=False)
+ # Delivery Amount
+ amount: Mapped[int] = mapped_column(BigInteger, nullable=False)
+ # Delivery Agent
+ agent_address: Mapped[str] = mapped_column(String(42), index=True, nullable=False)
+ # Data
+ data: Mapped[str] = mapped_column(Text)
+ # Create Delivery Blocktimestamp
+ create_blocktimestamp: Mapped[datetime] = mapped_column(DateTime, nullable=False)
+ # Create Transaction Hash
+ create_transaction_hash: Mapped[str] = mapped_column(
+ String(66), index=True, nullable=False
+ )
+ # Cancel Delivery Blocktimestamp
+ cancel_blocktimestamp: Mapped[datetime | None] = mapped_column(DateTime)
+ # Cancel Transaction Hash
+ cancel_transaction_hash: Mapped[str | None] = mapped_column(String(66), index=True)
+ # Confirm Delivery Blocktimestamp
+ confirm_blocktimestamp: Mapped[datetime | None] = mapped_column(DateTime)
+ # Confirm Transaction Hash
+ confirm_transaction_hash: Mapped[str | None] = mapped_column(String(66), index=True)
+ # Finish Delivery Blocktimestamp
+ finish_blocktimestamp: Mapped[datetime | None] = mapped_column(DateTime)
+ # Finish Transaction Hash
+ finish_transaction_hash: Mapped[str | None] = mapped_column(String(66), index=True)
+ # Abort Delivery Blocktimestamp
+ abort_blocktimestamp: Mapped[datetime | None] = mapped_column(DateTime)
+ # Abort Transaction Hash
+ abort_transaction_hash: Mapped[str | None] = mapped_column(String(66), index=True)
+ # Confirmation Status
+ confirmed: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
+ # Delivery Valid Status
+ valid: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
+ # Delivery Status(DeliveryStatus)
+ status: Mapped[int] = mapped_column(
+ BigInteger, nullable=False, default=DeliveryStatus.DELIVERY_CREATED
+ )
+
+ def json(self):
+ return {
+ "exchange_address": self.exchange_address,
+ "token_address": self.token_address,
+ "delivery_id": self.delivery_id,
+ "buyer_address": self.buyer_address,
+ "seller_address": self.seller_address,
+ "agent_address": self.agent_address,
+ "amount": self.amount,
+ "data": self.data,
+ "create_blocktimestamp": self.create_blocktimestamp,
+ "create_transaction_hash": self.create_transaction_hash,
+ "cancel_blocktimestamp": self.cancel_blocktimestamp,
+ "cancel_transaction_hash": self.cancel_transaction_hash,
+ "confirm_blocktimestamp": self.confirm_blocktimestamp,
+ "confirm_transaction_hash": self.confirm_transaction_hash,
+ "finish_blocktimestamp": self.finish_blocktimestamp,
+ "finish_transaction_hash": self.finish_transaction_hash,
+ "abort_blocktimestamp": self.abort_blocktimestamp,
+ "abort_transaction_hash": self.abort_transaction_hash,
+ "confirmed": self.confirmed,
+ "valid": self.valid,
+ "status": self.status,
+ }
+
+
+class IDXDeliveryBlockNumber(Base):
+ """Synchronized blockNumber of IDXDelivery"""
+
+ __tablename__ = "idx_delivery_block_number"
+
+ # target exchange address
+ exchange_address: Mapped[str] = mapped_column(String(42), primary_key=True)
+ # latest blockNumber
+ latest_block_number: Mapped[int] = mapped_column(BigInteger, nullable=False)
diff --git a/app/model/db/idx_personal_info.py b/app/model/db/idx_personal_info.py
index 14511b76..03e0d568 100644
--- a/app/model/db/idx_personal_info.py
+++ b/app/model/db/idx_personal_info.py
@@ -17,12 +17,21 @@
SPDX-License-Identifier: Apache-2.0
"""
-from sqlalchemy import JSON, BigInteger, String
+from datetime import datetime
+from enum import StrEnum
+
+import pytz
+from sqlalchemy import JSON, BigInteger, DateTime, String
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import Mapped, mapped_column
+import config
+
from .base import Base
+local_tz = pytz.timezone(config.TZ)
+utc_tz = pytz.timezone("UTC")
+
class IDXPersonalInfo(Base):
"""INDEX Personal information of the token holder (decrypted)"""
@@ -75,13 +84,19 @@ def _personal_info_setter(self, personal_info_dict: dict):
"tax_category": personal_info_dict.get("tax_category", None),
}
+ @staticmethod
+ def localize_datetime(_datetime: datetime) -> datetime | None:
+ if _datetime is None:
+ return None
+ return utc_tz.localize(_datetime).astimezone(local_tz)
+
def json(self):
return {
"id": self.id,
"account_address": self.account_address,
- "issuer_address": self.issuer_address,
"personal_info": self.personal_info,
- "created": self.created,
+ "created": self.localize_datetime(self.created),
+ "modified": self.localize_datetime(self.modified),
}
@@ -93,3 +108,44 @@ class IDXPersonalInfoBlockNumber(Base):
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
# latest blockNumber
latest_block_number: Mapped[int | None] = mapped_column(BigInteger)
+
+
+class PersonalInfoEventType(StrEnum):
+ REGISTER = "register"
+ MODIFY = "modify"
+
+
+class IDXPersonalInfoHistory(Base):
+ """Indexed personal information histories"""
+
+ __tablename__ = "idx_personal_info_history"
+
+ id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
+ # account address
+ account_address: Mapped[str | None] = mapped_column(String(42), index=True)
+ # issuer address
+ issuer_address: Mapped[str | None] = mapped_column(String(42), index=True)
+ # event type
+ event_type: Mapped[PersonalInfoEventType] = mapped_column(
+ String(10), index=True, nullable=False
+ )
+ # personal information
+ personal_info = mapped_column(JSON, nullable=False)
+ # block timestamp
+ block_timestamp: Mapped[datetime | None] = mapped_column(DateTime)
+
+ @staticmethod
+ def localize_datetime(_datetime: datetime) -> datetime | None:
+ if _datetime is None:
+ return None
+ return utc_tz.localize(_datetime).astimezone(local_tz)
+
+ def json(self):
+ return {
+ "id": self.id,
+ "account_address": self.account_address,
+ "event_type": self.event_type,
+ "personal_info": self.personal_info,
+ "block_timestamp": self.localize_datetime(self.block_timestamp),
+ "created": self.localize_datetime(self.created),
+ }
diff --git a/app/model/db/ledger.py b/app/model/db/ledger.py
index c8e976ed..51417c4c 100644
--- a/app/model/db/ledger.py
+++ b/app/model/db/ledger.py
@@ -22,7 +22,7 @@
from sqlalchemy import JSON, BigInteger, DateTime, Integer, String
from sqlalchemy.orm import Mapped, mapped_column
-from .base import Base
+from .base import Base, naive_utcnow
class Ledger(Base):
@@ -41,7 +41,7 @@ class Ledger(Base):
# created datetime(UTC)
# NOTE: Because Base's created column is subject to change in the data patch, define another column.
ledger_created: Mapped[datetime] = mapped_column(
- DateTime, nullable=False, default=datetime.utcnow
+ DateTime, nullable=False, default=naive_utcnow
)
@@ -69,6 +69,7 @@ class Ledger(Base):
}
],
"footers": [],
+ "some_personal_info_not_registered": "boolean",
},
],
"footers": [],
@@ -102,5 +103,5 @@ class LedgerDetailsData(Base):
# created datetime(UTC)
# NOTE: Because Base's created column is subject to change in the data patch, define another column.
data_created: Mapped[datetime] = mapped_column(
- DateTime, nullable=False, default=datetime.utcnow
+ DateTime, nullable=False, default=naive_utcnow
)
diff --git a/app/model/db/token.py b/app/model/db/token.py
index 7f92a81d..d6b0c7a9 100644
--- a/app/model/db/token.py
+++ b/app/model/db/token.py
@@ -23,7 +23,7 @@
from sqlalchemy import JSON, Boolean, DateTime, Integer, String
from sqlalchemy.orm import Mapped, mapped_column
-from .base import Base
+from .base import Base, naive_utcnow
class TokenType(str, Enum):
@@ -34,6 +34,7 @@ class TokenType(str, Enum):
class TokenVersion(StrEnum):
V_22_12 = "22_12"
V_23_12 = "23_12"
+ V_24_06 = "24_06"
class Token(Base):
@@ -84,9 +85,9 @@ class TokenCache(Base):
attributes: Mapped[dict] = mapped_column(JSON, nullable=False)
# cached datetime
cached_datetime: Mapped[datetime | None] = mapped_column(
- DateTime, default=datetime.utcnow
+ DateTime, default=naive_utcnow
)
# expiration datetime
expiration_datetime: Mapped[datetime | None] = mapped_column(
- DateTime, default=datetime.utcnow
+ DateTime, default=naive_utcnow
)
diff --git a/app/model/schema/__init__.py b/app/model/schema/__init__.py
index 57506363..0815f057 100644
--- a/app/model/schema/__init__.py
+++ b/app/model/schema/__init__.py
@@ -113,6 +113,19 @@
ScheduledEventIdResponse,
ScheduledEventResponse,
)
+from .settlement import (
+ AbortDVPDeliveryRequest,
+ CancelDVPDeliveryRequest,
+ CreateDVPAgentAccountRequest,
+ CreateDVPDeliveryRequest,
+ DVPAgentAccountChangeEOAPasswordRequest,
+ DVPAgentAccountResponse,
+ FinishDVPDeliveryRequest,
+ ListAllDVPAgentAccountResponse,
+ ListAllDVPDeliveriesQuery,
+ ListAllDVPDeliveriesResponse,
+ RetrieveDVPDeliveryResponse,
+)
from .token import (
IbetShareAdditionalIssue,
IbetShareCreate,
@@ -145,6 +158,8 @@
CreateTokenHoldersListRequest,
CreateTokenHoldersListResponse,
ListAllTokenHolderCollectionsResponse,
+ ListTokenHoldersPersonalInfoHistoryQuery,
+ ListTokenHoldersPersonalInfoHistoryResponse,
ListTokenHoldersPersonalInfoQuery,
ListTokenHoldersPersonalInfoResponse,
RetrieveTokenHoldersListResponse,
diff --git a/app/model/schema/base/base.py b/app/model/schema/base/base.py
index 34abe21f..5d1902df 100644
--- a/app/model/schema/base/base.py
+++ b/app/model/schema/base/base.py
@@ -30,10 +30,12 @@
class IbetStraightBondContractVersion(StrEnum):
V_22_12 = "22_12"
V_23_12 = "23_12"
+ V_24_06 = "24_06"
class IbetShareContractVersion(StrEnum):
V_22_12 = "22_12"
+ V_24_06 = "24_06"
MMDD_constr = Annotated[
diff --git a/app/model/schema/ledger.py b/app/model/schema/ledger.py
index 917aaa1f..740fd58c 100644
--- a/app/model/schema/ledger.py
+++ b/app/model/schema/ledger.py
@@ -126,6 +126,7 @@ class RetrieveLedgerDetailsHistoryResponse(BaseModel):
headers: Optional[List[dict]] = None
data: List[RetrieveLedgerDetailsDataHistoryResponse]
footers: Optional[List[dict]] = None
+ some_personal_info_not_registered: bool
class RetrieveLedgerHistoryResponse(BaseModel):
diff --git a/app/model/schema/personal_info.py b/app/model/schema/personal_info.py
index eda7142e..8226508d 100644
--- a/app/model/schema/personal_info.py
+++ b/app/model/schema/personal_info.py
@@ -18,6 +18,7 @@
"""
from datetime import datetime
+from enum import StrEnum
from typing import Annotated, List, Optional
from fastapi import Query
@@ -30,6 +31,11 @@
from .base import ResultSet, SortOrder
+class PersonalInfoEventType(StrEnum):
+ REGISTER = "register"
+ MODIFY = "modify"
+
+
class PersonalInfo(BaseModel):
key_manager: Optional[str] = Field(...)
name: Optional[str] = Field(...)
@@ -60,6 +66,18 @@ class PersonalInfoIndex(BaseModel):
account_address: str = Field(...)
personal_info: PersonalInfo = Field(...)
created: datetime
+ modified: datetime
+
+
+class PersonalInfoHistory(BaseModel):
+ """Personal Information History schema"""
+
+ id: int = Field(...)
+ account_address: str = Field(...)
+ event_type: PersonalInfoEventType = Field(...)
+ personal_info: PersonalInfo = Field(...)
+ block_timestamp: datetime = Field(...)
+ created: datetime
############################
diff --git a/app/model/schema/settlement.py b/app/model/schema/settlement.py
new file mode 100644
index 00000000..c450a8e2
--- /dev/null
+++ b/app/model/schema/settlement.py
@@ -0,0 +1,187 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+from datetime import datetime
+from enum import IntEnum
+from typing import Annotated, Literal, Optional
+
+from fastapi import Query
+from pydantic import BaseModel, Field, RootModel, field_validator
+from pydantic.dataclasses import dataclass
+
+from app.model import EthereumAddress
+from app.model.schema.base import ResultSet, SortOrder
+from app.utils.check_utils import check_value_is_encrypted
+from config import E2EE_REQUEST_ENABLED
+
+############################
+# COMMON
+############################
+
+
+class DeliveryStatus(IntEnum):
+ """DVP Delivery Status"""
+
+ DELIVERY_CREATED = 0
+ DELIVERY_CANCELED = 1
+ DELIVERY_CONFIRMED = 2
+ DELIVERY_FINISHED = 3
+ DELIVERY_ABORTED = 4
+
+
+############################
+# REQUEST
+############################
+class CreateDVPAgentAccountRequest(BaseModel):
+ """DVP agent account create schema (REQUEST)"""
+
+ eoa_password: str = Field(..., description="EOA keyfile password")
+
+ @field_validator("eoa_password")
+ @classmethod
+ def eoa_password_is_encrypted_value(cls, v):
+ if E2EE_REQUEST_ENABLED:
+ check_value_is_encrypted("eoa_password", v)
+ return v
+
+
+class DVPAgentAccountChangeEOAPasswordRequest(BaseModel):
+ """DVP agent account change EOA password schema (REQUEST)"""
+
+ old_eoa_password: str = Field(..., description="EOA keyfile password (old)")
+ eoa_password: str = Field(..., description="EOA keyfile password (new)")
+
+ @field_validator("old_eoa_password")
+ @classmethod
+ def old_eoa_password_is_encrypted_value(cls, v):
+ if E2EE_REQUEST_ENABLED:
+ check_value_is_encrypted("old_eoa_password", v)
+ return v
+
+ @field_validator("eoa_password")
+ @classmethod
+ def eoa_password_is_encrypted_value(cls, v):
+ if E2EE_REQUEST_ENABLED:
+ check_value_is_encrypted("eoa_password", v)
+ return v
+
+
+@dataclass
+class ListAllDVPDeliveriesQuery:
+ token_address: Annotated[Optional[str], Query(description="Token address")] = None
+ seller_address: Annotated[Optional[str], Query(description="Seller address")] = None
+ buyer_address: Annotated[Optional[str], Query(description="Buyer address")] = None
+ agent_address: Annotated[Optional[str], Query(description="Agent address")] = None
+ valid: Annotated[Optional[bool], Query(description="Valid flag")] = None
+ status: Annotated[
+ Optional[DeliveryStatus], Query(description="Delivery status")
+ ] = None
+ create_blocktimestamp_from: Annotated[
+ Optional[datetime], Query(description="Create block timestamp filter(From)")
+ ] = None
+ create_blocktimestamp_to: Annotated[
+ Optional[datetime], Query(description="Create block timestamp filter(To)")
+ ] = None
+
+ sort_order: Annotated[SortOrder, Query(description="0:asc, 1:desc")] = (
+ SortOrder.DESC
+ )
+ offset: Annotated[Optional[int], Query(description="Start position", ge=0)] = None
+ limit: Annotated[Optional[int], Query(description="Number of set", ge=0)] = None
+
+
+class CreateDVPDeliveryRequest(BaseModel):
+ """DVP delivery create schema (REQUEST)"""
+
+ token_address: EthereumAddress
+ buyer_address: EthereumAddress
+ amount: int = Field(..., ge=1, le=1_000_000_000_000)
+ agent_address: EthereumAddress
+ data: str
+
+
+class CancelDVPDeliveryRequest(BaseModel):
+ """DVP delivery cancel schema (REQUEST)"""
+
+ operation_type: Literal["Cancel"]
+
+
+class FinishDVPDeliveryRequest(BaseModel):
+ """DVP delivery finish schema (REQUEST)"""
+
+ operation_type: Literal["Finish"]
+ account_address: EthereumAddress = Field(..., description="Agent account address")
+ eoa_password: str = Field(..., description="Agent account key file password")
+
+
+class AbortDVPDeliveryRequest(BaseModel):
+ """DVP delivery abort schema (REQUEST)"""
+
+ operation_type: Literal["Abort"]
+ account_address: EthereumAddress = Field(..., description="Agent account address")
+ eoa_password: str = Field(..., description="Agent account key file password")
+
+
+############################
+# RESPONSE
+############################
+class DVPAgentAccountResponse(BaseModel):
+ """DVP agent account reference schema (RESPONSE)"""
+
+ account_address: str
+ is_deleted: bool
+
+
+class ListAllDVPAgentAccountResponse(RootModel[list[DVPAgentAccountResponse]]):
+ """DVP agent account list reference schema (RESPONSE)"""
+
+ pass
+
+
+class RetrieveDVPDeliveryResponse(BaseModel):
+ """Retrieve DVP delivery schema (Response)"""
+
+ exchange_address: str
+ delivery_id: int
+ token_address: str
+ buyer_address: str
+ seller_address: str
+ amount: int
+ agent_address: str
+ data: str = Field(examples=["{}", '{"type": "primary"}'])
+ create_blocktimestamp: str
+ create_transaction_hash: str
+ cancel_blocktimestamp: Optional[str] = Field(...)
+ cancel_transaction_hash: Optional[str] = Field(...)
+ confirm_blocktimestamp: Optional[str] = Field(...)
+ confirm_transaction_hash: Optional[str] = Field(...)
+ finish_blocktimestamp: Optional[str] = Field(...)
+ finish_transaction_hash: Optional[str] = Field(...)
+ abort_blocktimestamp: Optional[str] = Field(...)
+ abort_transaction_hash: Optional[str] = Field(...)
+ confirmed: bool
+ valid: bool
+ status: DeliveryStatus
+
+
+class ListAllDVPDeliveriesResponse(BaseModel):
+ """List all DVP delivery schema (Response)"""
+
+ result_set: ResultSet
+ deliveries: list[RetrieveDVPDeliveryResponse]
diff --git a/app/model/schema/token.py b/app/model/schema/token.py
index 65ccc721..0f4a47c8 100644
--- a/app/model/schema/token.py
+++ b/app/model/schema/token.py
@@ -27,7 +27,7 @@
from pydantic import BaseModel, Field, field_validator, model_validator
from pydantic.dataclasses import dataclass
-from app.model import EthereumAddress
+from app.model import EthereumAddress, ValidatedDatetimeStr
from .base import (
CURRENCY_str,
@@ -74,6 +74,7 @@ class IbetStraightBondCreate(BaseModel):
is_offering: Optional[bool] = None
tradable_exchange_contract_address: Optional[EthereumAddress] = None
personal_info_contract_address: Optional[EthereumAddress] = None
+ require_personal_info_registered: Optional[bool] = None
image_url: Optional[list[str]] = None
contact_information: Optional[str] = Field(default=None, max_length=2000)
privacy_policy: Optional[str] = Field(default=None, max_length=5000)
@@ -130,6 +131,7 @@ class IbetStraightBondUpdate(BaseModel):
is_redeemed: Optional[bool] = None
tradable_exchange_contract_address: Optional[EthereumAddress] = None
personal_info_contract_address: Optional[EthereumAddress] = None
+ require_personal_info_registered: Optional[bool] = None
contact_information: Optional[str] = Field(default=None, max_length=2000)
privacy_policy: Optional[str] = Field(default=None, max_length=5000)
transfer_approval_required: Optional[bool] = None
@@ -214,6 +216,7 @@ class IbetShareCreate(BaseModel):
is_offering: Optional[bool] = None
tradable_exchange_contract_address: Optional[EthereumAddress] = None
personal_info_contract_address: Optional[EthereumAddress] = None
+ require_personal_info_registered: Optional[bool] = None
contact_information: Optional[str] = Field(default=None, max_length=2000)
privacy_policy: Optional[str] = Field(default=None, max_length=5000)
transfer_approval_required: Optional[bool] = None
@@ -239,6 +242,7 @@ class IbetShareUpdate(BaseModel):
dividends: Optional[float] = Field(default=None, ge=0.00, le=5_000_000_000.00)
tradable_exchange_contract_address: Optional[EthereumAddress] = None
personal_info_contract_address: Optional[EthereumAddress] = None
+ require_personal_info_registered: Optional[bool] = None
transferable: Optional[bool] = None
status: Optional[bool] = None
is_offering: Optional[bool] = None
@@ -359,6 +363,7 @@ class ListAllHoldersSortItem(StrEnum):
balance = "balance"
pending_transfer = "pending_transfer"
locked = "locked"
+ balance_and_pending_transfer = "balance_and_pending_transfer"
key_manager = "key_manager"
holder_name = "holder_name"
@@ -391,6 +396,16 @@ class ListAllHoldersQuery:
description="search condition of locked amount(0:equal, 1:greater than or equal, 2:less than or equal)",
),
] = ValueOperator.EQUAL
+ balance_and_pending_transfer: Annotated[
+ Optional[int],
+ Query(description="number of balance plus pending transfer amount"),
+ ] = None
+ balance_and_pending_transfer_operator: Annotated[
+ Optional[ValueOperator],
+ Query(
+ description="search condition of balance plus pending transfer(0:equal, 1:greater than or equal, 2:less than or equal)",
+ ),
+ ] = ValueOperator.EQUAL
account_address: Annotated[
Optional[str], Query(description="account address(partial match)")
] = None
@@ -464,10 +479,10 @@ class ListTokenOperationLogHistoryQuery:
Optional[TokenUpdateOperationCategory], Query(description="Trigger of change")
] = None
created_from: Annotated[
- Optional[datetime], Query(description="Created datetime filter(From)")
+ Optional[ValidatedDatetimeStr], Query(description="created datetime (From)")
] = None
created_to: Annotated[
- Optional[datetime], Query(description="Created datetime filter(To)")
+ Optional[ValidatedDatetimeStr], Query(description="created datetime (To)")
] = None
sort_item: Annotated[ListTokenHistorySortItem, Query(description="Sort item")] = (
ListTokenHistorySortItem.created
@@ -515,6 +530,7 @@ class IbetStraightBondResponse(BaseModel):
is_offering: bool
tradable_exchange_contract_address: str
personal_info_contract_address: str
+ require_personal_info_registered: bool
contact_information: str
privacy_policy: str
issue_datetime: str
@@ -544,6 +560,7 @@ class IbetShareResponse(BaseModel):
is_offering: bool
tradable_exchange_contract_address: str
personal_info_contract_address: str
+ require_personal_info_registered: bool
contact_information: str
privacy_policy: str
issue_datetime: str
diff --git a/app/model/schema/token_holders.py b/app/model/schema/token_holders.py
index c03e9770..b72ee968 100644
--- a/app/model/schema/token_holders.py
+++ b/app/model/schema/token_holders.py
@@ -18,30 +18,99 @@
"""
import uuid
+from enum import StrEnum
from typing import Annotated, List, Optional
from fastapi import Query
from pydantic import BaseModel, ConfigDict, Field, NonNegativeInt, field_validator
+from pydantic.dataclasses import dataclass
+from app.model import ValidatedDatetimeStr
from app.model.db import TokenHolderBatchStatus
from app.model.schema.base import ResultSet, SortOrder
-from app.model.schema.personal_info import PersonalInfoIndex
+from app.model.schema.personal_info import (
+ PersonalInfoEventType,
+ PersonalInfoHistory,
+ PersonalInfoIndex,
+)
############################
# REQUEST
############################
-class ListTokenHoldersPersonalInfoQuery(BaseModel):
+class ListTokenHoldersPersonalInfoSortItem(StrEnum):
+ account_address = "account_address"
+ created = "created"
+ modified = "modified"
+
+
+@dataclass
+class ListTokenHoldersPersonalInfoQuery:
+ account_address: Annotated[Optional[str], Query(description="account address")] = (
+ None
+ )
+ created_from: Annotated[
+ Optional[ValidatedDatetimeStr], Query(description="created datetime (From)")
+ ] = None
+ created_to: Annotated[
+ Optional[ValidatedDatetimeStr], Query(description="created datetime (To)")
+ ] = None
+ modified_from: Annotated[
+ Optional[ValidatedDatetimeStr], Query(description="modified datetime (From)")
+ ] = None
+ modified_to: Annotated[
+ Optional[ValidatedDatetimeStr], Query(description="modified datetime (To)")
+ ] = None
+
+ sort_item: Annotated[
+ ListTokenHoldersPersonalInfoSortItem, Query(description="sort item")
+ ] = ListTokenHoldersPersonalInfoSortItem.created
+ sort_order: Annotated[
+ Optional[SortOrder], Query(description="sort order(0: ASC, 1: DESC)")
+ ] = SortOrder.ASC
+
offset: Annotated[Optional[NonNegativeInt], Query(description="start position")] = (
None
)
limit: Annotated[Optional[NonNegativeInt], Query(description="number of set")] = (
None
)
+
+
+@dataclass
+class ListTokenHoldersPersonalInfoHistoryQuery:
+ account_address: Annotated[Optional[str], Query(description="account address")] = (
+ None
+ )
+ event_type: Annotated[
+ Optional[PersonalInfoEventType], Query(description="event type")
+ ] = None
+ block_timestamp_from: Annotated[
+ Optional[ValidatedDatetimeStr],
+ Query(description="block timestamp datetime (From)"),
+ ] = None
+ block_timestamp_to: Annotated[
+ Optional[ValidatedDatetimeStr],
+ Query(description="block timestamp datetime (To)"),
+ ] = None
+ created_from: Annotated[
+ Optional[ValidatedDatetimeStr], Query(description="created datetime (From)")
+ ] = None
+ created_to: Annotated[
+ Optional[ValidatedDatetimeStr], Query(description="created datetime (To)")
+ ] = None
+
sort_order: Annotated[
- Optional[SortOrder], Query(description="sort order(0: ASC, 1: DESC)")
+ Optional[SortOrder], Query(description="sort order (0: ASC, 1: DESC)")
] = SortOrder.ASC
+ offset: Annotated[Optional[NonNegativeInt], Query(description="start position")] = (
+ None
+ )
+ limit: Annotated[Optional[NonNegativeInt], Query(description="number of set")] = (
+ None
+ )
+
class CreateTokenHoldersListRequest(BaseModel):
"""Create Token Holders List schema (REQUEST)"""
@@ -79,6 +148,13 @@ class ListTokenHoldersPersonalInfoResponse(BaseModel):
personal_info: List[PersonalInfoIndex]
+class ListTokenHoldersPersonalInfoHistoryResponse(BaseModel):
+ """List All Token Holders PersonalInfo Histories (Response)"""
+
+ result_set: ResultSet
+ personal_info: List[PersonalInfoHistory]
+
+
class CreateTokenHoldersListResponse(BaseModel):
"""Create Token Holders List schema (RESPONSE)"""
diff --git a/app/model/schema/transfer.py b/app/model/schema/transfer.py
index cfceb082..203811ea 100644
--- a/app/model/schema/transfer.py
+++ b/app/model/schema/transfer.py
@@ -17,14 +17,16 @@
SPDX-License-Identifier: Apache-2.0
"""
+from datetime import datetime
from enum import Enum, IntEnum
from typing import Annotated, List, Optional
from fastapi import Query
-from pydantic import BaseModel, Field, NonNegativeInt, conint
+from pydantic import BaseModel, Field, NonNegativeInt
from pydantic.dataclasses import dataclass
from app.model.schema.base import ResultSet, SortOrder
+from app.model.schema.base.base import ValueOperator
from .personal_info import PersonalInfo
@@ -54,11 +56,38 @@ class ListTransferHistorySortItem(str, Enum):
BLOCK_TIMESTAMP = "block_timestamp"
FROM_ADDRESS = "from_address"
TO_ADDRESS = "to_address"
+ FROM_ADDRESS_NAME = "from_address_name"
+ TO_ADDRESS_NAME = "to_address_name"
AMOUNT = "amount"
@dataclass
class ListTransferHistoryQuery:
+ block_timestamp_from: Annotated[
+ Optional[datetime], Query(description="block timestamp (From)")
+ ] = None
+ block_timestamp_to: Annotated[
+ Optional[datetime], Query(descriptio0n="block timestamp (To)")
+ ] = None
+ from_address: Annotated[
+ Optional[str], Query(description="transfer source address")
+ ] = None
+ to_address: Annotated[
+ Optional[str], Query(description="transfer destination address")
+ ] = None
+ from_address_name: Annotated[
+ Optional[str], Query(description="name of transfer source address")
+ ] = None
+ to_address_name: Annotated[
+ Optional[str], Query(description="name of transfer destination address")
+ ] = None
+ amount: Annotated[Optional[int], Query(description="transfer amount")] = None
+ amount_operator: Annotated[
+ Optional[ValueOperator],
+ Query(
+ description="value filter condition(0: equal, 1: greater than, 2: less than)",
+ ),
+ ] = ValueOperator.EQUAL
source_event: Annotated[
Optional[TransferSourceEventType], Query(description="source event of transfer")
] = None
diff --git a/app/routers/account.py b/app/routers/account.py
index c80bf85e..35b98cf9 100644
--- a/app/routers/account.py
+++ b/app/routers/account.py
@@ -20,17 +20,17 @@
import hashlib
import re
import secrets
-from datetime import datetime, timedelta
+from datetime import UTC, datetime, timedelta
from typing import List, Optional, Sequence
import boto3
import eth_keyfile
+import pytz
from coincurve import PublicKey
from Crypto.PublicKey import RSA
from eth_utils import keccak, to_checksum_address
from fastapi import APIRouter, Header, Request
from fastapi.exceptions import HTTPException
-from pytz import timezone
from sqlalchemy import select
from sqlalchemy.exc import IntegrityError as SAIntegrityError
@@ -80,7 +80,7 @@
router = APIRouter(tags=["account"])
-local_tz = timezone(TZ)
+local_tz = pytz.timezone(TZ)
# POST: /accounts
@@ -453,7 +453,9 @@ async def create_auth_token(
hashed_token = hashlib.sha256(new_token.encode()).hexdigest()
# Get current datetime
- current_datetime_utc = timezone("UTC").localize(datetime.utcnow())
+ current_datetime_utc = pytz.timezone("UTC").localize(
+ datetime.now(UTC).replace(tzinfo=None)
+ )
current_datetime_local = current_datetime_utc.astimezone(local_tz).isoformat()
# Register auth token
@@ -470,7 +472,7 @@ async def create_auth_token(
expiration_datetime = auth_token.usage_start + timedelta(
seconds=auth_token.valid_duration
)
- if datetime.utcnow() <= expiration_datetime:
+ if datetime.now(UTC).replace(tzinfo=None) <= expiration_datetime:
raise AuthTokenAlreadyExistsError()
# Update auth token
auth_token.auth_token = hashed_token
diff --git a/app/routers/bond.py b/app/routers/bond.py
index 6f682b38..f4867b86 100644
--- a/app/routers/bond.py
+++ b/app/routers/bond.py
@@ -18,13 +18,13 @@
"""
import uuid
-from datetime import datetime
+from datetime import UTC, datetime
from typing import List, Optional, Sequence
+import pytz
from eth_keyfile import decode_keyfile_json
from fastapi import APIRouter, Depends, Header, Query, Request
from fastapi.exceptions import HTTPException
-from pytz import timezone
from sqlalchemy import (
String,
and_,
@@ -41,6 +41,7 @@
select,
)
from sqlalchemy.orm import aliased
+from sqlalchemy.sql.functions import coalesce
import config
from app import log
@@ -50,6 +51,7 @@
ContractRevertError,
InvalidParameterError,
OperationNotAllowedStateError,
+ OperationNotSupportedVersionError,
SendTransactionError,
)
from app.model.blockchain import (
@@ -168,8 +170,8 @@
)
LOG = log.get_logger()
-local_tz = timezone(config.TZ)
-utc_tz = timezone("UTC")
+local_tz = pytz.timezone(config.TZ)
+utc_tz = pytz.timezone("UTC")
# POST: /bond/tokens
@@ -258,6 +260,7 @@ async def issue_token(
"is_redeemed",
"tradable_exchange_contract_address",
"personal_info_contract_address",
+ "require_personal_info_registered",
"contact_information",
"privacy_policy",
"transfer_approval_required",
@@ -312,7 +315,9 @@ async def issue_token(
_utxo.token_address = contract_address
_utxo.amount = token.total_supply
_utxo.block_number = block["number"]
- _utxo.block_timestamp = datetime.utcfromtimestamp(block["timestamp"])
+ _utxo.block_timestamp = datetime.fromtimestamp(block["timestamp"], UTC).replace(
+ tzinfo=None
+ )
db.add(_utxo)
token_status = 1 # succeeded
@@ -325,7 +330,7 @@ async def issue_token(
_token.token_address = contract_address
_token.abi = abi
_token.token_status = token_status
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# Register operation log
@@ -389,7 +394,7 @@ async def list_all_tokens(
bond_token = (
await IbetStraightBondContract(token.token_address).get()
).__dict__
- issue_datetime_utc = timezone("UTC").localize(token.created)
+ issue_datetime_utc = pytz.timezone("UTC").localize(token.created)
bond_token["issue_datetime"] = issue_datetime_utc.astimezone(
local_tz
).isoformat()
@@ -430,7 +435,7 @@ async def retrieve_token(db: DBAsyncSession, token_address: str):
# Get contract data
bond_token = (await IbetStraightBondContract(token_address).get()).__dict__
- issue_datetime_utc = timezone("UTC").localize(_token.created)
+ issue_datetime_utc = pytz.timezone("UTC").localize(_token.created)
bond_token["issue_datetime"] = issue_datetime_utc.astimezone(local_tz).isoformat()
bond_token["token_status"] = _token.token_status
bond_token["contract_version"] = _token.version
@@ -451,13 +456,14 @@ async def retrieve_token(db: DBAsyncSession, token_address: str):
InvalidParameterError,
SendTransactionError,
ContractRevertError,
+ OperationNotSupportedVersionError,
),
)
async def update_token(
db: DBAsyncSession,
request: Request,
token_address: str,
- token: IbetStraightBondUpdate,
+ update_data: IbetStraightBondUpdate,
issuer_address: str = Header(...),
eoa_password: Optional[str] = Header(None),
auth_token: Optional[str] = Header(None),
@@ -505,12 +511,30 @@ async def update_token(
if _token.token_status == 0:
raise InvalidParameterError("this token is temporarily unavailable")
+ # Verify that the token version supports the operation
+ if _token.version < TokenVersion.V_23_12:
+ if (
+ update_data.face_value_currency is not None
+ or update_data.interest_payment_currency is not None
+ or update_data.redemption_value_currency is not None
+ or update_data.base_fx_rate is not None
+ ):
+ raise OperationNotSupportedVersionError(
+ f"the operation is not supported in {_token.version}"
+ )
+
+ if _token.version < TokenVersion.V_24_06:
+ if update_data.require_personal_info_registered is not None:
+ raise OperationNotSupportedVersionError(
+ f"the operation is not supported in {_token.version}"
+ )
+
# Send transaction
try:
token_contract = IbetStraightBondContract(token_address)
original_contents = (await token_contract.get()).__dict__
await token_contract.update(
- data=UpdateParams(**token.model_dump()),
+ data=UpdateParams(**update_data.model_dump()),
tx_from=issuer_address,
private_key=private_key,
)
@@ -522,7 +546,7 @@ async def update_token(
operation_log.token_address = token_address
operation_log.issuer_address = issuer_address
operation_log.type = TokenType.IBET_STRAIGHT_BOND.value
- operation_log.arguments = token.model_dump(exclude_none=True)
+ operation_log.arguments = update_data.model_dump(exclude_none=True)
operation_log.original_contents = original_contents
operation_log.operation_category = TokenUpdateOperationCategory.UPDATE.value
db.add(operation_log)
@@ -563,14 +587,20 @@ async def list_bond_operation_log_history(
)
)
if request_query.created_from:
+ _created_from = datetime.strptime(
+ request_query.created_from + ".000000", "%Y-%m-%d %H:%M:%S.%f"
+ )
stmt = stmt.where(
TokenUpdateOperationLog.created
- >= local_tz.localize(request_query.created_from).astimezone(utc_tz)
+ >= local_tz.localize(_created_from).astimezone(utc_tz)
)
if request_query.created_to:
+ _created_to = datetime.strptime(
+ request_query.created_to + ".999999", "%Y-%m-%d %H:%M:%S.%f"
+ )
stmt = stmt.where(
TokenUpdateOperationLog.created
- <= local_tz.localize(request_query.created_to).astimezone(utc_tz)
+ <= local_tz.localize(_created_to).astimezone(utc_tz)
)
count = await db.scalar(select(func.count()).select_from(stmt.subquery()))
@@ -680,7 +710,7 @@ async def list_additional_issuance_history(
history = []
for _event in _events:
- block_timestamp_utc = timezone("UTC").localize(_event.block_timestamp)
+ block_timestamp_utc = pytz.timezone("UTC").localize(_event.block_timestamp)
history.append(
{
"transaction_hash": _event.transaction_hash,
@@ -796,11 +826,6 @@ async def list_all_additional_issue_upload(
get_query: ListAllAdditionalIssueUploadQuery = Depends(),
issuer_address: Optional[str] = Header(None),
):
- processed = get_query.processed
- sort_order = get_query.sort_order
- offset = get_query.offset
- limit = get_query.limit
-
# Get a list of uploads
stmt = select(BatchIssueRedeemUpload).where(
and_(
@@ -815,28 +840,28 @@ async def list_all_additional_issue_upload(
total = await db.scalar(select(func.count()).select_from(stmt.subquery()))
- if processed is not None:
- stmt = stmt.where(BatchIssueRedeemUpload.processed == processed)
+ if get_query.processed is not None:
+ stmt = stmt.where(BatchIssueRedeemUpload.processed == get_query.processed)
count = await db.scalar(select(func.count()).select_from(stmt.subquery()))
# Sort
- if sort_order == 0: # ASC
+ if get_query.sort_order == 0: # ASC
stmt = stmt.order_by(BatchIssueRedeemUpload.created)
else: # DESC
stmt = stmt.order_by(desc(BatchIssueRedeemUpload.created))
# Pagination
- if limit is not None:
- stmt = stmt.limit(limit)
- if offset is not None:
- stmt = stmt.offset(offset)
+ if get_query.limit is not None:
+ stmt = stmt.limit(get_query.limit)
+ if get_query.offset is not None:
+ stmt = stmt.offset(get_query.offset)
_upload_list: Sequence[BatchIssueRedeemUpload] = (await db.scalars(stmt)).all()
uploads = []
for _upload in _upload_list:
- created_utc = timezone("UTC").localize(_upload.created)
+ created_utc = pytz.timezone("UTC").localize(_upload.created)
uploads.append(
{
"batch_id": _upload.upload_id,
@@ -851,8 +876,8 @@ async def list_all_additional_issue_upload(
resp = {
"result_set": {
"count": count,
- "offset": offset,
- "limit": limit,
+ "offset": get_query.offset,
+ "limit": get_query.limit,
"total": total,
},
"uploads": uploads,
@@ -1042,11 +1067,6 @@ async def list_redeem_history(
get_query: ListRedeemHistoryQuery = Depends(),
):
"""List redemption history"""
- sort_item = get_query.sort_item
- sort_order = get_query.sort_order
- offset = get_query.offset
- limit = get_query.limit
-
# Get token
_token: Token | None = (
await db.scalars(
@@ -1077,26 +1097,26 @@ async def list_redeem_history(
count = total
# Sort
- sort_attr = getattr(IDXIssueRedeem, sort_item.value, None)
- if sort_order == 0: # ASC
+ sort_attr = getattr(IDXIssueRedeem, get_query.sort_item.value, None)
+ if get_query.sort_order == 0: # ASC
stmt = stmt.order_by(sort_attr)
else: # DESC
stmt = stmt.order_by(desc(sort_attr))
- if sort_item != IDXIssueRedeemSortItem.BLOCK_TIMESTAMP:
+ if get_query.sort_item != IDXIssueRedeemSortItem.BLOCK_TIMESTAMP:
# NOTE: Set secondary sort for consistent results
stmt = stmt.order_by(desc(IDXIssueRedeem.block_timestamp))
# Pagination
- if limit is not None:
- stmt = stmt.limit(limit)
- if offset is not None:
- stmt = stmt.offset(offset)
+ if get_query.limit is not None:
+ stmt = stmt.limit(get_query.limit)
+ if get_query.offset is not None:
+ stmt = stmt.offset(get_query.offset)
_events: Sequence[IDXIssueRedeem] = (await db.scalars(stmt)).all()
history = []
for _event in _events:
- block_timestamp_utc = timezone("UTC").localize(_event.block_timestamp)
+ block_timestamp_utc = pytz.timezone("UTC").localize(_event.block_timestamp)
history.append(
{
"transaction_hash": _event.transaction_hash,
@@ -1112,8 +1132,8 @@ async def list_redeem_history(
{
"result_set": {
"count": count,
- "offset": offset,
- "limit": limit,
+ "offset": get_query.offset,
+ "limit": get_query.limit,
"total": total,
},
"history": history,
@@ -1212,11 +1232,6 @@ async def list_all_redeem_upload(
get_query: ListAllRedeemUploadQuery = Depends(),
issuer_address: Optional[str] = Header(None),
):
- processed = get_query.processed
- sort_order = get_query.sort_order
- offset = get_query.offset
- limit = get_query.limit
-
# Get a list of uploads
stmt = select(BatchIssueRedeemUpload).where(
and_(
@@ -1232,28 +1247,28 @@ async def list_all_redeem_upload(
total = await db.scalar(select(func.count()).select_from(stmt.subquery()))
- if processed is not None:
- stmt = stmt.where(BatchIssueRedeemUpload.processed == processed)
+ if get_query.processed is not None:
+ stmt = stmt.where(BatchIssueRedeemUpload.processed == get_query.processed)
count = await db.scalar(select(func.count()).select_from(stmt.subquery()))
# Sort
- if sort_order == 0: # ASC
+ if get_query.sort_order == 0: # ASC
stmt = stmt.order_by(BatchIssueRedeemUpload.created)
else: # DESC
stmt = stmt.order_by(desc(BatchIssueRedeemUpload.created))
# Pagination
- if limit is not None:
- stmt = stmt.limit(limit)
- if offset is not None:
- stmt = stmt.offset(offset)
+ if get_query.limit is not None:
+ stmt = stmt.limit(get_query.limit)
+ if get_query.offset is not None:
+ stmt = stmt.offset(get_query.offset)
_upload_list: Sequence[BatchIssueRedeemUpload] = (await db.scalars(stmt)).all()
uploads = []
for _upload in _upload_list:
- created_utc = timezone("UTC").localize(_upload.created)
+ created_utc = pytz.timezone("UTC").localize(_upload.created)
uploads.append(
{
"batch_id": _upload.upload_id,
@@ -1268,8 +1283,8 @@ async def list_all_redeem_upload(
resp = {
"result_set": {
"count": count,
- "offset": offset,
- "limit": limit,
+ "offset": get_query.offset,
+ "limit": get_query.limit,
"total": total,
},
"uploads": uploads,
@@ -1489,10 +1504,10 @@ async def list_all_scheduled_events(
token_events = []
for _token_event in _token_events:
- scheduled_datetime_utc = timezone("UTC").localize(
+ scheduled_datetime_utc = pytz.timezone("UTC").localize(
_token_event.scheduled_datetime
)
- created_utc = timezone("UTC").localize(_token_event.created)
+ created_utc = pytz.timezone("UTC").localize(_token_event.created)
token_events.append(
{
"scheduled_event_id": _token_event.event_id,
@@ -1515,7 +1530,12 @@ async def list_all_scheduled_events(
"/tokens/{token_address}/scheduled_events",
response_model=ScheduledEventIdResponse,
responses=get_routers_responses(
- 422, 401, 404, AuthorizationError, InvalidParameterError
+ 422,
+ 401,
+ 404,
+ AuthorizationError,
+ InvalidParameterError,
+ OperationNotSupportedVersionError,
),
)
async def schedule_new_update_event(
@@ -1564,6 +1584,24 @@ async def schedule_new_update_event(
if _token.token_status == 0:
raise InvalidParameterError("this token is temporarily unavailable")
+ # Verify that the token version supports the operation
+ if _token.version < TokenVersion.V_23_12:
+ if (
+ event_data.data.face_value_currency is not None
+ or event_data.data.interest_payment_currency is not None
+ or event_data.data.redemption_value_currency is not None
+ or event_data.data.base_fx_rate is not None
+ ):
+ raise OperationNotSupportedVersionError(
+ f"the operation is not supported in {_token.version}"
+ )
+
+ if _token.version < TokenVersion.V_24_06:
+ if event_data.data.require_personal_info_registered is not None:
+ raise OperationNotSupportedVersionError(
+ f"the operation is not supported in {_token.version}"
+ )
+
# Register an event
_scheduled_event = ScheduledEvents()
_scheduled_event.event_id = str(uuid.uuid4())
@@ -1626,8 +1664,10 @@ async def retrieve_token_event(
if _token_event is None:
raise HTTPException(status_code=404, detail="event not found")
- scheduled_datetime_utc = timezone("UTC").localize(_token_event.scheduled_datetime)
- created_utc = timezone("UTC").localize(_token_event.created)
+ scheduled_datetime_utc = pytz.timezone("UTC").localize(
+ _token_event.scheduled_datetime
+ )
+ created_utc = pytz.timezone("UTC").localize(_token_event.created)
return json_response(
{
"scheduled_event_id": _token_event.event_id,
@@ -1694,8 +1734,10 @@ async def delete_scheduled_event(
if _token_event is None:
raise HTTPException(status_code=404, detail="event not found")
- scheduled_datetime_utc = timezone("UTC").localize(_token_event.scheduled_datetime)
- created_utc = timezone("UTC").localize(_token_event.created)
+ scheduled_datetime_utc = pytz.timezone("UTC").localize(
+ _token_event.scheduled_datetime
+ )
+ created_utc = pytz.timezone("UTC").localize(_token_event.created)
rtn = {
"scheduled_event_id": _token_event.event_id,
"token_address": token_address,
@@ -1726,21 +1768,6 @@ async def list_all_holders(
issuer_address: str = Header(...),
):
"""List all bond token holders"""
- include_former_holder = get_query.include_former_holder
- balance = get_query.balance
- balance_operator = get_query.balance_operator
- pending_transfer = get_query.pending_transfer
- pending_transfer_operator = get_query.pending_transfer_operator
- locked = get_query.locked
- locked_operator = get_query.locked_operator
- account_address = get_query.account_address
- holder_name = get_query.holder_name
- key_manager = get_query.key_manager
- sort_item = get_query.sort_item
- sort_order = get_query.sort_order
- offset = get_query.offset
- limit = get_query.limit
-
# Validate Headers
validate_headers(issuer_address=(issuer_address, address_is_valid_address))
@@ -1807,7 +1834,7 @@ async def list_all_holders(
total = await db.scalar(select(func.count()).select_from(stmt.subquery()))
- if not include_former_holder:
+ if not get_query.include_former_holder:
stmt = stmt.where(
or_(
IDXPosition.balance != 0,
@@ -1818,75 +1845,109 @@ async def list_all_holders(
)
)
- if balance is not None and balance_operator is not None:
- match balance_operator:
+ if get_query.balance is not None and get_query.balance_operator is not None:
+ match get_query.balance_operator:
case ValueOperator.EQUAL:
- stmt = stmt.where(IDXPosition.balance == balance)
+ stmt = stmt.where(IDXPosition.balance == get_query.balance)
case ValueOperator.GTE:
- stmt = stmt.where(IDXPosition.balance >= balance)
+ stmt = stmt.where(IDXPosition.balance >= get_query.balance)
+ case ValueOperator.LTE:
+ stmt = stmt.where(IDXPosition.balance <= get_query.balance)
+
+ if (
+ get_query.pending_transfer is not None
+ and get_query.pending_transfer_operator is not None
+ ):
+ match get_query.pending_transfer_operator:
+ case ValueOperator.EQUAL:
+ stmt = stmt.where(
+ IDXPosition.pending_transfer == get_query.pending_transfer
+ )
+ case ValueOperator.GTE:
+ stmt = stmt.where(
+ IDXPosition.pending_transfer >= get_query.pending_transfer
+ )
case ValueOperator.LTE:
- stmt = stmt.where(IDXPosition.balance <= balance)
+ stmt = stmt.where(
+ IDXPosition.pending_transfer <= get_query.pending_transfer
+ )
- if pending_transfer is not None and pending_transfer_operator is not None:
- match pending_transfer_operator:
+ if get_query.locked is not None and get_query.locked_operator is not None:
+ match get_query.locked_operator:
case ValueOperator.EQUAL:
- stmt = stmt.where(IDXPosition.pending_transfer == pending_transfer)
+ stmt = stmt.having(coalesce(locked_value, 0) == get_query.locked)
case ValueOperator.GTE:
- stmt = stmt.where(IDXPosition.pending_transfer >= pending_transfer)
+ stmt = stmt.having(coalesce(locked_value, 0) >= get_query.locked)
case ValueOperator.LTE:
- stmt = stmt.where(IDXPosition.pending_transfer <= pending_transfer)
+ stmt = stmt.having(coalesce(locked_value, 0) <= get_query.locked)
- if locked is not None and locked_operator is not None:
- match locked_operator:
+ if (
+ get_query.balance_and_pending_transfer is not None
+ and get_query.balance_and_pending_transfer_operator is not None
+ ):
+ match get_query.balance_and_pending_transfer_operator:
case ValueOperator.EQUAL:
- stmt = stmt.having(locked_value == locked)
+ stmt = stmt.where(
+ IDXPosition.balance + IDXPosition.pending_transfer
+ == get_query.balance_and_pending_transfer
+ )
case ValueOperator.GTE:
- stmt = stmt.having(locked_value >= locked)
+ stmt = stmt.where(
+ IDXPosition.balance + IDXPosition.pending_transfer
+ >= get_query.balance_and_pending_transfer
+ )
case ValueOperator.LTE:
- stmt = stmt.having(locked_value <= locked)
+ stmt = stmt.where(
+ IDXPosition.balance + IDXPosition.pending_transfer
+ <= get_query.balance_and_pending_transfer
+ )
- if account_address is not None:
- stmt = stmt.where(IDXPosition.account_address.like("%" + account_address + "%"))
+ if get_query.account_address is not None:
+ stmt = stmt.where(
+ IDXPosition.account_address.like("%" + get_query.account_address + "%")
+ )
- if holder_name is not None:
+ if get_query.holder_name is not None:
stmt = stmt.where(
IDXPersonalInfo._personal_info["name"]
.as_string()
- .like("%" + holder_name + "%")
+ .like("%" + get_query.holder_name + "%")
)
- if key_manager is not None:
+ if get_query.key_manager is not None:
stmt = stmt.where(
IDXPersonalInfo._personal_info["key_manager"]
.as_string()
- .like("%" + key_manager + "%")
+ .like("%" + get_query.key_manager + "%")
)
count = await db.scalar(select(func.count()).select_from(stmt.subquery()))
# Sort
- if sort_item == ListAllHoldersSortItem.holder_name:
+ if get_query.sort_item == ListAllHoldersSortItem.holder_name:
sort_attr = IDXPersonalInfo._personal_info["name"].as_string()
- elif sort_item == ListAllHoldersSortItem.key_manager:
+ elif get_query.sort_item == ListAllHoldersSortItem.key_manager:
sort_attr = IDXPersonalInfo._personal_info["key_manager"].as_string()
- elif sort_item == ListAllHoldersSortItem.locked:
+ elif get_query.sort_item == ListAllHoldersSortItem.locked:
sort_attr = locked_value
+ elif get_query.sort_item == ListAllHoldersSortItem.balance_and_pending_transfer:
+ sort_attr = IDXPosition.balance + IDXPosition.pending_transfer
else:
- sort_attr = getattr(IDXPosition, sort_item)
+ sort_attr = getattr(IDXPosition, get_query.sort_item)
- if sort_order == 0: # ASC
+ if get_query.sort_order == 0: # ASC
stmt = stmt.order_by(asc(sort_attr))
else: # DESC
stmt = stmt.order_by(desc(sort_attr))
- if sort_item != ListAllHoldersSortItem.created:
+ if get_query.sort_item != ListAllHoldersSortItem.created:
# NOTE: Set secondary sort for consistent results
stmt = stmt.order_by(asc(IDXPosition.created))
# Pagination
- if limit is not None:
- stmt = stmt.limit(limit)
- if offset is not None:
- stmt = stmt.offset(offset)
+ if get_query.limit is not None:
+ stmt = stmt.limit(get_query.limit)
+ if get_query.offset is not None:
+ stmt = stmt.offset(get_query.offset)
_holders: Sequence[
tuple[IDXPosition, int, IDXPersonalInfo | None, datetime | None]
@@ -1939,8 +2000,8 @@ async def list_all_holders(
"result_set": {
"count": count,
"total": total,
- "limit": limit,
- "offset": offset,
+ "limit": get_query.limit,
+ "offset": get_query.offset,
},
"holders": holders,
}
@@ -2264,11 +2325,6 @@ async def list_all_personal_info_batch_registration_uploads(
get_query: ListAllPersonalInfoBatchRegistrationUploadQuery = Depends(),
):
"""List all personal information batch registration uploads"""
- status = get_query.status
- sort_order = get_query.sort_order
- offset = get_query.offset
- limit = get_query.limit
-
# Verify that the token is issued by the issuer_address
_token: Token | None = (
await db.scalars(
@@ -2296,22 +2352,22 @@ async def list_all_personal_info_batch_registration_uploads(
total = await db.scalar(select(func.count()).select_from(stmt.subquery()))
- if status is not None:
- stmt = stmt.where(BatchRegisterPersonalInfoUpload.status == status)
+ if get_query.status is not None:
+ stmt = stmt.where(BatchRegisterPersonalInfoUpload.status == get_query.status)
count = await db.scalar(select(func.count()).select_from(stmt.subquery()))
# Sort
- if sort_order == 0: # ASC
+ if get_query.sort_order == 0: # ASC
stmt = stmt.order_by(BatchRegisterPersonalInfoUpload.created)
else: # DESC
stmt = stmt.order_by(desc(BatchRegisterPersonalInfoUpload.created))
# Pagination
- if limit is not None:
- stmt = stmt.limit(limit)
- if offset is not None:
- stmt = stmt.offset(offset)
+ if get_query.limit is not None:
+ stmt = stmt.limit(get_query.limit)
+ if get_query.offset is not None:
+ stmt = stmt.offset(get_query.offset)
_upload_list: Sequence[BatchRegisterPersonalInfoUpload] = (
await db.scalars(stmt)
@@ -2319,7 +2375,7 @@ async def list_all_personal_info_batch_registration_uploads(
uploads = []
for _upload in _upload_list:
- created_utc = timezone("UTC").localize(_upload.created)
+ created_utc = pytz.timezone("UTC").localize(_upload.created)
uploads.append(
{
"batch_id": _upload.upload_id,
@@ -2332,8 +2388,8 @@ async def list_all_personal_info_batch_registration_uploads(
{
"result_set": {
"count": count,
- "offset": offset,
- "limit": limit,
+ "offset": get_query.offset,
+ "limit": get_query.limit,
"total": total,
},
"uploads": uploads,
@@ -2419,7 +2475,7 @@ async def batch_register_personal_info(
{
"batch_id": batch_id,
"status": batch.status,
- "created": timezone("UTC")
+ "created": pytz.timezone("UTC")
.localize(batch.created)
.astimezone(local_tz)
.isoformat(),
@@ -2644,7 +2700,7 @@ async def list_all_lock_events_by_bond(
for lock_event in lock_events:
token: Token = lock_event.Token
bond_contract = await IbetStraightBondContract(token.token_address).get()
- block_timestamp_utc = timezone("UTC").localize(lock_event.block_timestamp)
+ block_timestamp_utc = pytz.timezone("UTC").localize(lock_event.block_timestamp)
resp_data.append(
{
"category": lock_event.category,
@@ -2760,10 +2816,10 @@ async def transfer_ownership(
async def list_transfer_history(
db: DBAsyncSession,
token_address: str,
- request_query: ListTransferHistoryQuery = Depends(),
+ query: ListTransferHistoryQuery = Depends(),
):
"""List token transfer history"""
- # Get token
+ # Check if the token has been issued
_token: Token | None = (
await db.scalars(
select(Token)
@@ -2804,33 +2860,71 @@ async def list_transfer_history(
)
.where(IDXTransfer.token_address == token_address)
)
-
total = await db.scalar(select(func.count()).select_from(stmt.subquery()))
- if request_query.source_event is not None:
- stmt = stmt.where(IDXTransfer.source_event == request_query.source_event)
- if request_query.data is not None:
+ # Filter
+ if query.block_timestamp_from is not None:
stmt = stmt.where(
- cast(IDXTransfer.data, String).like("%" + request_query.data + "%")
+ IDXTransfer.block_timestamp
+ >= local_tz.localize(query.block_timestamp_from).astimezone(UTC)
)
-
+ if query.block_timestamp_to is not None:
+ stmt = stmt.where(
+ IDXTransfer.block_timestamp
+ <= local_tz.localize(query.block_timestamp_to).astimezone(UTC)
+ )
+ if query.from_address is not None:
+ stmt = stmt.where(IDXTransfer.from_address == query.from_address)
+ if query.to_address is not None:
+ stmt = stmt.where(IDXTransfer.to_address == query.to_address)
+ if query.from_address_name:
+ stmt = stmt.where(
+ from_address_personal_info._personal_info["name"]
+ .as_string()
+ .like("%" + query.from_address_name + "%")
+ )
+ if query.to_address_name:
+ stmt = stmt.where(
+ to_address_personal_info._personal_info["name"]
+ .as_string()
+ .like("%" + query.to_address_name + "%")
+ )
+ if query.amount is not None and query.amount_operator is not None:
+ match query.amount_operator:
+ case ValueOperator.EQUAL:
+ stmt = stmt.where(IDXTransfer.amount == query.amount)
+ case ValueOperator.GTE:
+ stmt = stmt.where(IDXTransfer.amount >= query.amount)
+ case ValueOperator.LTE:
+ stmt = stmt.where(IDXTransfer.amount <= query.amount)
+ if query.source_event is not None:
+ stmt = stmt.where(IDXTransfer.source_event == query.source_event)
+ if query.data is not None:
+ stmt = stmt.where(cast(IDXTransfer.data, String).like("%" + query.data + "%"))
count = await db.scalar(select(func.count()).select_from(stmt.subquery()))
# Sort
- sort_attr = getattr(IDXTransfer, request_query.sort_item.value, None)
- if request_query.sort_order == 0: # ASC
+ match query.sort_item:
+ case ListTransferHistorySortItem.FROM_ADDRESS_NAME:
+ sort_attr = from_address_personal_info._personal_info["name"].as_string()
+ case ListTransferHistorySortItem.TO_ADDRESS_NAME:
+ sort_attr = to_address_personal_info._personal_info["name"].as_string()
+ case _:
+ sort_attr = getattr(IDXTransfer, query.sort_item.value, None)
+
+ if query.sort_order == 0: # ASC
stmt = stmt.order_by(sort_attr)
else: # DESC
stmt = stmt.order_by(desc(sort_attr))
- if request_query.sort_item != ListTransferHistorySortItem.BLOCK_TIMESTAMP:
+ if query.sort_item != ListTransferHistorySortItem.BLOCK_TIMESTAMP:
# NOTE: Set secondary sort for consistent results
stmt = stmt.order_by(desc(IDXTransfer.block_timestamp))
# Pagination
- if request_query.limit is not None:
- stmt = stmt.limit(request_query.limit)
- if request_query.offset is not None:
- stmt = stmt.offset(request_query.offset)
+ if query.limit is not None:
+ stmt = stmt.limit(query.limit)
+ if query.offset is not None:
+ stmt = stmt.offset(query.offset)
_transfers: Sequence[
tuple[IDXTransfer, IDXPersonalInfo | None, IDXPersonalInfo | None]
@@ -2838,7 +2932,7 @@ async def list_transfer_history(
transfer_history = []
for _transfer, _from_address_personal_info, _to_address_personal_info in _transfers:
- block_timestamp_utc = timezone("UTC").localize(_transfer.block_timestamp)
+ block_timestamp_utc = pytz.timezone("UTC").localize(_transfer.block_timestamp)
transfer_history.append(
{
"transaction_hash": _transfer.transaction_hash,
@@ -2866,8 +2960,8 @@ async def list_transfer_history(
{
"result_set": {
"count": count,
- "offset": request_query.offset,
- "limit": request_query.limit,
+ "offset": query.offset,
+ "limit": query.limit,
"total": total,
},
"transfer_history": transfer_history,
@@ -3024,14 +3118,6 @@ async def list_token_transfer_approval_history(
get_query: ListTransferApprovalHistoryQuery = Depends(),
):
"""List token transfer approval history"""
- from_address = get_query.from_address
- to_address = get_query.to_address
- status = get_query.status
- sort_item = get_query.sort_item
- sort_order = get_query.sort_order
- offset = get_query.offset
- limit = get_query.limit
-
# Get token
_token: Token | None = (
await db.scalars(
@@ -3148,33 +3234,33 @@ async def list_token_transfer_approval_history(
total = await db.scalar(select(func.count()).select_from(stmt.subquery()))
# Search Filter
- if from_address is not None:
- stmt = stmt.where(subquery.from_address == from_address)
- if to_address is not None:
- stmt = stmt.where(subquery.to_address == to_address)
- if status is not None:
- stmt = stmt.where(literal_column("status").in_(status))
+ if get_query.from_address is not None:
+ stmt = stmt.where(subquery.from_address == get_query.from_address)
+ if get_query.to_address is not None:
+ stmt = stmt.where(subquery.to_address == get_query.to_address)
+ if get_query.status is not None:
+ stmt = stmt.where(literal_column("status").in_(get_query.status))
count = await db.scalar(select(func.count()).select_from(stmt.subquery()))
# Sort
- if sort_item != IDXTransferApprovalsSortItem.STATUS:
- sort_attr = getattr(subquery, sort_item, None)
+ if get_query.sort_item != IDXTransferApprovalsSortItem.STATUS:
+ sort_attr = getattr(subquery, get_query.sort_item, None)
else:
sort_attr = literal_column("status")
- if sort_order == 0: # ASC
+ if get_query.sort_order == 0: # ASC
stmt = stmt.order_by(sort_attr)
else: # DESC
stmt = stmt.order_by(desc(sort_attr))
- if sort_item != IDXTransferApprovalsSortItem.ID:
+ if get_query.sort_item != IDXTransferApprovalsSortItem.ID:
# NOTE: Set secondary sort for consistent results
stmt = stmt.order_by(desc(subquery.id))
# Pagination
- if limit is not None:
- stmt = stmt.limit(limit)
- if offset is not None:
- stmt = stmt.offset(offset)
+ if get_query.limit is not None:
+ stmt = stmt.limit(get_query.limit)
+ if get_query.offset is not None:
+ stmt = stmt.offset(get_query.offset)
_transfer_approvals: Sequence[
tuple[
@@ -3216,12 +3302,12 @@ async def list_token_transfer_approval_history(
else:
issuer_cancelable = True
- application_datetime_utc = timezone("UTC").localize(
+ application_datetime_utc = pytz.timezone("UTC").localize(
_transfer_approval.application_datetime
)
application_datetime = application_datetime_utc.astimezone(local_tz).isoformat()
- application_blocktimestamp_utc = timezone("UTC").localize(
+ application_blocktimestamp_utc = pytz.timezone("UTC").localize(
_transfer_approval.application_blocktimestamp
)
application_blocktimestamp = application_blocktimestamp_utc.astimezone(
@@ -3229,7 +3315,7 @@ async def list_token_transfer_approval_history(
).isoformat()
if _transfer_approval.approval_datetime is not None:
- approval_datetime_utc = timezone("UTC").localize(
+ approval_datetime_utc = pytz.timezone("UTC").localize(
_transfer_approval.approval_datetime
)
approval_datetime = approval_datetime_utc.astimezone(local_tz).isoformat()
@@ -3237,7 +3323,7 @@ async def list_token_transfer_approval_history(
approval_datetime = None
if _transfer_approval.approval_blocktimestamp is not None:
- approval_blocktimestamp_utc = timezone("UTC").localize(
+ approval_blocktimestamp_utc = pytz.timezone("UTC").localize(
_transfer_approval.approval_blocktimestamp
)
approval_blocktimestamp = approval_blocktimestamp_utc.astimezone(
@@ -3247,7 +3333,7 @@ async def list_token_transfer_approval_history(
approval_blocktimestamp = None
if _transfer_approval.cancellation_blocktimestamp is not None:
- cancellation_blocktimestamp_utc = timezone("UTC").localize(
+ cancellation_blocktimestamp_utc = pytz.timezone("UTC").localize(
_transfer_approval.cancellation_blocktimestamp
)
cancellation_blocktimestamp = cancellation_blocktimestamp_utc.astimezone(
@@ -3302,8 +3388,8 @@ async def list_token_transfer_approval_history(
{
"result_set": {
"count": count,
- "offset": offset,
- "limit": limit,
+ "offset": get_query.offset,
+ "limit": get_query.limit,
"total": total,
},
"transfer_approval_history": transfer_approval_history,
@@ -3470,7 +3556,7 @@ async def update_transfer_approval(
# a cancelTransfer is performed immediately.
# - CANCEL -> cancelTransfer
try:
- now = str(datetime.utcnow().timestamp())
+ now = str(datetime.now(UTC).replace(tzinfo=None).timestamp())
if data.operation_type == UpdateTransferApprovalOperationType.APPROVE:
if _transfer_approval.exchange_address == config.ZERO_ADDRESS:
_data = {
@@ -3657,12 +3743,12 @@ async def retrieve_transfer_approval_history(
else:
issuer_cancelable = True
- application_datetime_utc = timezone("UTC").localize(
+ application_datetime_utc = pytz.timezone("UTC").localize(
_transfer_approval.application_datetime
)
application_datetime = application_datetime_utc.astimezone(local_tz).isoformat()
- application_blocktimestamp_utc = timezone("UTC").localize(
+ application_blocktimestamp_utc = pytz.timezone("UTC").localize(
_transfer_approval.application_blocktimestamp
)
application_blocktimestamp = application_blocktimestamp_utc.astimezone(
@@ -3670,7 +3756,7 @@ async def retrieve_transfer_approval_history(
).isoformat()
if _transfer_approval.approval_datetime is not None:
- approval_datetime_utc = timezone("UTC").localize(
+ approval_datetime_utc = pytz.timezone("UTC").localize(
_transfer_approval.approval_datetime
)
approval_datetime = approval_datetime_utc.astimezone(local_tz).isoformat()
@@ -3678,7 +3764,7 @@ async def retrieve_transfer_approval_history(
approval_datetime = None
if _transfer_approval.approval_blocktimestamp is not None:
- approval_blocktimestamp_utc = timezone("UTC").localize(
+ approval_blocktimestamp_utc = pytz.timezone("UTC").localize(
_transfer_approval.approval_blocktimestamp
)
approval_blocktimestamp = approval_blocktimestamp_utc.astimezone(
@@ -3688,7 +3774,7 @@ async def retrieve_transfer_approval_history(
approval_blocktimestamp = None
if _transfer_approval.cancellation_blocktimestamp is not None:
- cancellation_blocktimestamp_utc = timezone("UTC").localize(
+ cancellation_blocktimestamp_utc = pytz.timezone("UTC").localize(
_transfer_approval.cancellation_blocktimestamp
)
cancellation_blocktimestamp = cancellation_blocktimestamp_utc.astimezone(
@@ -3923,7 +4009,7 @@ async def list_bulk_transfer_upload(
uploads = []
for _upload in _uploads:
- created_utc = timezone("UTC").localize(_upload.created)
+ created_utc = pytz.timezone("UTC").localize(_upload.created)
uploads.append(
{
"issuer_address": _upload.issuer_address,
diff --git a/app/routers/e2e_messaging.py b/app/routers/e2e_messaging.py
index d73fa287..697265fd 100644
--- a/app/routers/e2e_messaging.py
+++ b/app/routers/e2e_messaging.py
@@ -20,7 +20,7 @@
import json
import re
import secrets
-from datetime import datetime
+from datetime import UTC, datetime
from typing import List, Optional, Sequence
import boto3
@@ -163,7 +163,9 @@ async def create_account(
_account_rsa_key.rsa_private_key = rsa_private_key
_account_rsa_key.rsa_public_key = rsa_public_key
_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(rsa_passphrase)
- _account_rsa_key.block_timestamp = datetime.utcfromtimestamp(block["timestamp"])
+ _account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
db.add(_account_rsa_key)
# Insert initial transaction execution management record
diff --git a/app/routers/ledger.py b/app/routers/ledger.py
index c20fbbfc..465867ac 100644
--- a/app/routers/ledger.py
+++ b/app/routers/ledger.py
@@ -30,6 +30,7 @@
from app.database import DBAsyncSession
from app.exceptions import Integer64bitLimitExceededError, InvalidParameterError
from app.model.blockchain import (
+ ContractPersonalInfoType,
IbetShareContract,
IbetStraightBondContract,
PersonalInfoContract,
@@ -249,18 +250,30 @@ async def retrieve_ledger_history(
_details.token_detail_type for _details in _ibet_fin_details_list
]
# Update PersonalInfo
+ some_personal_info_not_registered = False
for details in resp["details"]:
if details["token_detail_type"] in _ibet_fin_token_detail_type_list:
for data in details["data"]:
- personal_info = await __get_personal_info(
+ personal_info, _pi_not_registered = await __get_personal_info(
token_address=token_address,
token_type=_token.type,
account_address=data["account_address"],
db=db,
)
- if personal_info is not None:
- data["name"] = personal_info.get("name", None)
- data["address"] = personal_info.get("address", None)
+ data["name"] = personal_info.get("name", None)
+ data["address"] = personal_info.get("address", None)
+ if _pi_not_registered:
+ some_personal_info_not_registered = True
+ details["some_personal_info_not_registered"] = (
+ some_personal_info_not_registered
+ )
+ else:
+ # NOTE: Implementation for backward compatibility
+ # In specifications prior to v24.6, the item "some_personal_info_not_registered" does not exist,
+ # so data for which the item does not exist is overwritten with False.
+ for details in resp["details"]:
+ if details.get("some_personal_info_not_registered") is None:
+ details["some_personal_info_not_registered"] = False
return json_response(resp)
@@ -878,52 +891,88 @@ async def delete_ledger_details_data(
async def __get_personal_info(
token_address: str, token_type: str, account_address: str, db: AsyncSession
-):
+) -> tuple[dict, bool]:
+ # NOTE:
+ # For tokens with require_personal_info_registered = False, search only indexed data.
+ # If indexed data does not exist, return the default value.
+
token: Token | None = (
await db.scalars(
select(Token).where(Token.token_address == token_address).limit(1)
)
).first()
if token is None:
- return None
- else:
- _idx_personal_info: IDXPersonalInfo | None = (
- await db.scalars(
- select(IDXPersonalInfo)
- .where(
- and_(
- IDXPersonalInfo.account_address == account_address,
- IDXPersonalInfo.issuer_address == token.issuer_address,
- )
+ personal_info_not_registered = True
+ return ContractPersonalInfoType().model_dump(), personal_info_not_registered
+
+ # Issuer cannot have any personal info
+ if account_address == token.issuer_address:
+ personal_info_not_registered = False
+ return (
+ ContractPersonalInfoType(
+ key_manager=None,
+ name=None,
+ address=None,
+ postal_code=None,
+ email=None,
+ birth=None,
+ ).model_dump(),
+ personal_info_not_registered,
+ )
+
+ # Search indexed data
+ _idx_personal_info: IDXPersonalInfo | None = (
+ await db.scalars(
+ select(IDXPersonalInfo)
+ .where(
+ and_(
+ IDXPersonalInfo.account_address == account_address,
+ IDXPersonalInfo.issuer_address == token.issuer_address,
)
+ )
+ .limit(1)
+ )
+ ).first()
+ if (
+ _idx_personal_info is not None
+ and any(_idx_personal_info.personal_info.values()) is not False
+ ):
+ # Get personal info from DB
+ personal_info_not_registered = False
+ return _idx_personal_info.personal_info, personal_info_not_registered
+
+ # Get token attributes
+ token_contract = None
+ if token_type == TokenType.IBET_SHARE.value:
+ token_contract = await IbetShareContract(token_address).get()
+ elif token_type == TokenType.IBET_STRAIGHT_BOND.value:
+ token_contract = await IbetStraightBondContract(token_address).get()
+
+ if token_contract.require_personal_info_registered is True:
+ # Get issuer account
+ issuer_account = (
+ await db.scalars(
+ select(Account)
+ .where(Account.issuer_address == token.issuer_address)
.limit(1)
)
).first()
- if _idx_personal_info is not None:
- # Get personal info from DB
- personal_info = _idx_personal_info.personal_info
+
+ # Retrieve personal info from contract storage
+ personal_info_contract = PersonalInfoContract(
+ issuer=issuer_account,
+ contract_address=token_contract.personal_info_contract_address,
+ )
+ personal_info = await personal_info_contract.get_info(
+ account_address=account_address, default_value=None
+ )
+ if any(personal_info.values()) is False:
+ personal_info_not_registered = True
else:
- # Get issuer account
- issuer_account = (
- await db.scalars(
- select(Account)
- .where(Account.issuer_address == token.issuer_address)
- .limit(1)
- )
- ).first()
-
- # Get personal info from contract
- token_contract = None
- if token_type == TokenType.IBET_SHARE.value:
- token_contract = await IbetShareContract(token_address).get()
- elif token_type == TokenType.IBET_STRAIGHT_BOND.value:
- token_contract = await IbetStraightBondContract(token_address).get()
-
- personal_info_contract = PersonalInfoContract(
- issuer=issuer_account,
- contract_address=token_contract.personal_info_contract_address,
- )
- personal_info = await personal_info_contract.get_info(
- account_address=account_address, default_value=None
- )
- return personal_info
+ personal_info_not_registered = False
+ else:
+ # Do not retrieve contract data and return the default value
+ personal_info = ContractPersonalInfoType().model_dump()
+ personal_info_not_registered = True
+
+ return personal_info, personal_info_not_registered
diff --git a/app/routers/settlement.py b/app/routers/settlement.py
new file mode 100644
index 00000000..590b298e
--- /dev/null
+++ b/app/routers/settlement.py
@@ -0,0 +1,695 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+import re
+import secrets
+from datetime import UTC
+from typing import Optional, Sequence
+
+import boto3
+import eth_keyfile
+import pytz
+from coincurve import PublicKey
+from eth_keyfile import decode_keyfile_json
+from eth_utils import keccak, to_checksum_address
+from fastapi import APIRouter, Depends, Header, HTTPException, Path, Request
+from sqlalchemy import and_, desc, func, select
+
+import config
+from app.database import DBAsyncSession
+from app.exceptions import InvalidParameterError, SendTransactionError
+from app.model.blockchain.exchange import IbetSecurityTokenDVP
+from app.model.blockchain.tx_params.ibet_security_token_dvp import (
+ AbortDeliveryParams,
+ CancelDeliveryParams,
+ CreateDeliveryParams,
+ FinishDeliveryParams,
+)
+from app.model.db import DVPAgentAccount, IDXDelivery, TransactionLock
+from app.model.schema import (
+ AbortDVPDeliveryRequest,
+ CancelDVPDeliveryRequest,
+ CreateDVPAgentAccountRequest,
+ CreateDVPDeliveryRequest,
+ DVPAgentAccountChangeEOAPasswordRequest,
+ DVPAgentAccountResponse,
+ FinishDVPDeliveryRequest,
+ ListAllDVPAgentAccountResponse,
+ ListAllDVPDeliveriesQuery,
+ ListAllDVPDeliveriesResponse,
+ RetrieveDVPDeliveryResponse,
+)
+from app.utils.check_utils import (
+ address_is_valid_address,
+ check_auth,
+ eoa_password_is_encrypted_value,
+ validate_headers,
+)
+from app.utils.docs_utils import get_routers_responses
+from app.utils.e2ee_utils import E2EEUtils
+from app.utils.fastapi_utils import json_response
+from config import (
+ AWS_KMS_GENERATE_RANDOM_ENABLED,
+ AWS_REGION_NAME,
+ E2EE_REQUEST_ENABLED,
+ EOA_PASSWORD_PATTERN,
+ EOA_PASSWORD_PATTERN_MSG,
+)
+
+router = APIRouter(prefix="/settlement", tags=["token_common"])
+
+local_tz = pytz.timezone(config.TZ)
+
+
+# POST: /settlement/dvp/agent/accounts
+@router.post(
+ "/dvp/agent/accounts",
+ operation_id="CreateDVPAgentAccount",
+ response_model=DVPAgentAccountResponse,
+ responses=get_routers_responses(422, InvalidParameterError),
+)
+async def create_account(
+ db: DBAsyncSession,
+ create_req: CreateDVPAgentAccountRequest,
+):
+ """Create DVP-Payment Agent Account"""
+
+ # Check Password Policy(EOA password)
+ eoa_password = (
+ E2EEUtils.decrypt(create_req.eoa_password)
+ if E2EE_REQUEST_ENABLED
+ else create_req.eoa_password
+ )
+ if not re.match(EOA_PASSWORD_PATTERN, eoa_password):
+ raise InvalidParameterError(EOA_PASSWORD_PATTERN_MSG)
+
+ # Generate Ethereum Key
+ if AWS_KMS_GENERATE_RANDOM_ENABLED:
+ kms = boto3.client(service_name="kms", region_name=AWS_REGION_NAME)
+ result = kms.generate_random(NumberOfBytes=32)
+ private_key = keccak(result.get("Plaintext"))
+ else:
+ private_key = keccak(secrets.token_bytes(32))
+ public_key = PublicKey.from_valid_secret(private_key).format(compressed=False)[1:]
+ addr = to_checksum_address(keccak(public_key)[-20:])
+ keyfile_json = eth_keyfile.create_keyfile_json(
+ private_key=private_key, password=eoa_password.encode("utf-8"), kdf="pbkdf2"
+ )
+
+ # Register account data to the DB
+ _account = DVPAgentAccount()
+ _account.account_address = addr
+ _account.keyfile = keyfile_json
+ _account.eoa_password = E2EEUtils.encrypt(eoa_password)
+ _account.is_deleted = False
+ db.add(_account)
+
+ # Insert initial transaction execution management record
+ _tm = TransactionLock()
+ _tm.tx_from = addr
+ db.add(_tm)
+
+ await db.commit()
+
+ return json_response(
+ {
+ "account_address": _account.account_address,
+ "is_deleted": _account.is_deleted,
+ }
+ )
+
+
+# GET: /settlement/dvp/agent/accounts
+@router.get(
+ "/dvp/agent/accounts",
+ operation_id="ListAllDVPAgentAccount",
+ response_model=ListAllDVPAgentAccountResponse,
+)
+async def list_all_accounts(db: DBAsyncSession):
+ """List all DVP-Payment Agent accounts"""
+
+ _accounts: Sequence[DVPAgentAccount] = (
+ await db.scalars(select(DVPAgentAccount))
+ ).all()
+
+ account_list = [
+ {
+ "account_address": _account.account_address,
+ "is_deleted": _account.is_deleted,
+ }
+ for _account in _accounts
+ ]
+ return json_response(account_list)
+
+
+# DELETE: /settlement/dvp/agent/accounts/{account_address}
+@router.delete(
+ "/dvp/agent/account/{account_address}",
+ operation_id="DeleteDVPAgentAccount",
+ response_model=DVPAgentAccountResponse,
+ responses=get_routers_responses(404),
+)
+async def delete_account(db: DBAsyncSession, account_address: str):
+ """Logically delete an DVP-Payment Agent Account"""
+
+ # Search for an account
+ _account: DVPAgentAccount | None = (
+ await db.scalars(
+ select(DVPAgentAccount)
+ .where(DVPAgentAccount.account_address == account_address)
+ .limit(1)
+ )
+ ).first()
+ if _account is None:
+ raise HTTPException(status_code=404, detail="account is not exists")
+
+ # Update account
+ _account.is_deleted = True
+ await db.merge(_account)
+ await db.commit()
+
+ return json_response(
+ {
+ "account_address": _account.account_address,
+ "is_deleted": _account.is_deleted,
+ }
+ )
+
+
+# POST: /settlement/dvp/agent/accounts/{account_address}/eoa_password
+@router.post(
+ "/dvp/agent/account/{account_address}/eoa_password",
+ operation_id="ChangeDVPAgentAccountPassword",
+ response_model=None,
+ responses=get_routers_responses(404, 422, InvalidParameterError),
+)
+async def change_eoa_password(
+ db: DBAsyncSession,
+ account_address: str,
+ change_req: DVPAgentAccountChangeEOAPasswordRequest,
+):
+ """Change Account's EOA Password"""
+
+ # Search for an account
+ _account: DVPAgentAccount | None = (
+ await db.scalars(
+ select(DVPAgentAccount)
+ .where(DVPAgentAccount.account_address == account_address)
+ .limit(1)
+ )
+ ).first()
+ if _account is None:
+ raise HTTPException(status_code=404, detail="account is not exists")
+
+ # Check Old Password
+ old_eoa_password = (
+ E2EEUtils.decrypt(change_req.old_eoa_password)
+ if E2EE_REQUEST_ENABLED
+ else change_req.old_eoa_password
+ )
+ correct_eoa_password = E2EEUtils.decrypt(_account.eoa_password)
+ if old_eoa_password != correct_eoa_password:
+ raise InvalidParameterError("old password mismatch")
+
+ # Check Password Policy
+ eoa_password = (
+ E2EEUtils.decrypt(change_req.eoa_password)
+ if E2EE_REQUEST_ENABLED
+ else change_req.eoa_password
+ )
+ if not re.match(EOA_PASSWORD_PATTERN, eoa_password):
+ raise InvalidParameterError(EOA_PASSWORD_PATTERN_MSG)
+
+ # Get Ethereum Key
+ private_key = eth_keyfile.decode_keyfile_json(
+ raw_keyfile_json=_account.keyfile, password=old_eoa_password.encode("utf-8")
+ )
+
+ # Create New Ethereum Key File
+ keyfile_json = eth_keyfile.create_keyfile_json(
+ private_key=private_key, password=eoa_password.encode("utf-8"), kdf="pbkdf2"
+ )
+
+ # Update data
+ _account.keyfile = keyfile_json
+ _account.eoa_password = E2EEUtils.encrypt(eoa_password)
+ await db.merge(_account)
+
+ await db.commit()
+
+ return
+
+
+# GET: /settlement/dvp/{exchange_address}/deliveries
+@router.get(
+ "/dvp/{exchange_address}/deliveries",
+ operation_id="ListAllDVPDeliveries",
+ response_model=ListAllDVPDeliveriesResponse,
+ responses=get_routers_responses(404, 422, InvalidParameterError),
+)
+async def list_all_dvp_deliveries(
+ db: DBAsyncSession,
+ exchange_address: str,
+ request_query: ListAllDVPDeliveriesQuery = Depends(),
+):
+ """List of DVP delivery"""
+ stmt = select(IDXDelivery).where(
+ IDXDelivery.exchange_address == exchange_address,
+ )
+ total = await db.scalar(select(func.count()).select_from(stmt.subquery()))
+
+ if request_query.token_address is not None:
+ stmt = stmt.where(IDXDelivery.token_address == request_query.token_address)
+ if request_query.seller_address is not None:
+ stmt = stmt.where(IDXDelivery.seller_address == request_query.seller_address)
+ if request_query.agent_address is not None:
+ stmt = stmt.where(IDXDelivery.agent_address == request_query.agent_address)
+ if request_query.valid is not None:
+ stmt = stmt.where(IDXDelivery.valid == request_query.valid)
+ if request_query.status is not None:
+ stmt = stmt.where(IDXDelivery.status == request_query.status)
+ if request_query.create_blocktimestamp_from is not None:
+ stmt = stmt.where(
+ IDXDelivery.create_blocktimestamp
+ >= local_tz.localize(request_query.create_blocktimestamp_from).astimezone(
+ tz=UTC
+ )
+ )
+ if request_query.create_blocktimestamp_to is not None:
+ stmt = stmt.where(
+ IDXDelivery.create_blocktimestamp
+ <= local_tz.localize(request_query.create_blocktimestamp_to).astimezone(
+ tz=UTC
+ )
+ )
+
+ count = await db.scalar(select(func.count()).select_from(stmt.subquery()))
+
+ # Sort
+ if request_query.sort_order == 0: # ASC
+ stmt = stmt.order_by(IDXDelivery.create_blocktimestamp)
+ else: # DESC
+ stmt = stmt.order_by(desc(IDXDelivery.create_blocktimestamp))
+
+ # Pagination
+ if request_query.limit is not None:
+ stmt = stmt.limit(request_query.limit)
+ if request_query.offset is not None:
+ stmt = stmt.offset(request_query.offset)
+
+ _deliveries: Sequence[IDXDelivery] = (await db.scalars(stmt)).all()
+
+ deliveries = []
+ for _delivery in _deliveries:
+ if _delivery.create_blocktimestamp is not None:
+ create_blocktimestamp = (
+ local_tz.localize(_delivery.create_blocktimestamp)
+ .astimezone(tz=UTC)
+ .isoformat()
+ )
+ else:
+ create_blocktimestamp = None
+ if _delivery.cancel_blocktimestamp is not None:
+ cancel_blocktimestamp = (
+ local_tz.localize(_delivery.cancel_blocktimestamp)
+ .astimezone(tz=UTC)
+ .isoformat()
+ )
+ else:
+ cancel_blocktimestamp = None
+ if _delivery.confirm_blocktimestamp is not None:
+ confirm_blocktimestamp = (
+ local_tz.localize(_delivery.confirm_blocktimestamp)
+ .astimezone(tz=UTC)
+ .isoformat()
+ )
+ else:
+ confirm_blocktimestamp = None
+ if _delivery.finish_blocktimestamp is not None:
+ finish_blocktimestamp = (
+ local_tz.localize(_delivery.finish_blocktimestamp)
+ .astimezone(tz=UTC)
+ .isoformat()
+ )
+ else:
+ finish_blocktimestamp = None
+ if _delivery.abort_blocktimestamp is not None:
+ abort_blocktimestamp = (
+ local_tz.localize(_delivery.abort_blocktimestamp)
+ .astimezone(tz=UTC)
+ .isoformat()
+ )
+ else:
+ abort_blocktimestamp = None
+
+ deliveries.append(
+ {
+ "exchange_address": _delivery.exchange_address,
+ "delivery_id": _delivery.delivery_id,
+ "token_address": _delivery.token_address,
+ "buyer_address": _delivery.buyer_address,
+ "seller_address": _delivery.seller_address,
+ "amount": _delivery.amount,
+ "agent_address": _delivery.agent_address,
+ "data": _delivery.data,
+ "create_blocktimestamp": create_blocktimestamp,
+ "create_transaction_hash": _delivery.create_transaction_hash,
+ "cancel_blocktimestamp": cancel_blocktimestamp,
+ "cancel_transaction_hash": _delivery.cancel_transaction_hash,
+ "confirm_blocktimestamp": confirm_blocktimestamp,
+ "confirm_transaction_hash": _delivery.confirm_transaction_hash,
+ "finish_blocktimestamp": finish_blocktimestamp,
+ "finish_transaction_hash": _delivery.finish_transaction_hash,
+ "abort_blocktimestamp": abort_blocktimestamp,
+ "abort_transaction_hash": _delivery.abort_transaction_hash,
+ "confirmed": _delivery.confirmed,
+ "valid": _delivery.valid,
+ "status": _delivery.status,
+ }
+ )
+
+ return json_response(
+ {
+ "result_set": {
+ "count": count,
+ "offset": request_query.offset,
+ "limit": request_query.limit,
+ "total": total,
+ },
+ "deliveries": deliveries,
+ }
+ )
+
+
+# POST: /settlement/dvp/{exchange_address}/deliveries
+@router.post(
+ "/dvp/{exchange_address}/deliveries",
+ operation_id="CreateDVPDelivery",
+ response_model=None,
+ responses=get_routers_responses(
+ 404, 422, InvalidParameterError, SendTransactionError
+ ),
+)
+async def create_dvp_delivery(
+ db: DBAsyncSession,
+ req: Request,
+ exchange_address: str,
+ data: CreateDVPDeliveryRequest,
+ issuer_address: str = Header(...),
+ eoa_password: Optional[str] = Header(None),
+ auth_token: Optional[str] = Header(None),
+):
+ # Validate Headers
+ validate_headers(
+ issuer_address=(issuer_address, address_is_valid_address),
+ eoa_password=(eoa_password, eoa_password_is_encrypted_value),
+ )
+
+ # Authentication
+ _account, decrypt_password = await check_auth(
+ request=req,
+ db=db,
+ issuer_address=issuer_address,
+ eoa_password=eoa_password,
+ auth_token=auth_token,
+ )
+
+ # Get private key
+ keyfile_json = _account.keyfile
+ private_key = decode_keyfile_json(
+ raw_keyfile_json=keyfile_json, password=decrypt_password.encode("utf-8")
+ )
+
+ # Create delivery
+ dvp_contract = IbetSecurityTokenDVP(contract_address=exchange_address)
+ try:
+ _data = {
+ "token_address": data.token_address,
+ "buyer_address": data.buyer_address,
+ "amount": data.amount,
+ "agent_address": data.agent_address,
+ "data": data.data,
+ }
+ await dvp_contract.create_delivery(
+ data=CreateDeliveryParams(**_data),
+ tx_from=issuer_address,
+ private_key=private_key,
+ )
+ except SendTransactionError:
+ raise SendTransactionError("failed to create delivery")
+
+ return
+
+
+# GET: /settlement/dvp/{exchange_address}/delivery/{delivery_id}
+@router.get(
+ "/dvp/{exchange_address}/delivery/{delivery_id}",
+ operation_id="RetrieveDVPDelivery",
+ response_model=RetrieveDVPDeliveryResponse,
+ responses=get_routers_responses(404, 422, InvalidParameterError),
+)
+async def retrieve_dvp_delivery(
+ db: DBAsyncSession,
+ exchange_address: str = Path(..., description="Exchange Address"),
+ delivery_id: int = Path(..., description="Delivery Id"),
+):
+ """Retrieve a dvp delivery"""
+ _delivery: IDXDelivery | None = (
+ await db.scalars(
+ select(IDXDelivery)
+ .where(
+ and_(
+ IDXDelivery.exchange_address == exchange_address,
+ IDXDelivery.delivery_id == delivery_id,
+ )
+ )
+ .limit(1)
+ )
+ ).first()
+ if _delivery is None:
+ raise HTTPException(status_code=404, detail="delivery not found")
+
+ if _delivery.create_blocktimestamp is not None:
+ create_blocktimestamp = (
+ local_tz.localize(_delivery.create_blocktimestamp)
+ .astimezone(tz=UTC)
+ .isoformat()
+ )
+ else:
+ create_blocktimestamp = None
+ if _delivery.cancel_blocktimestamp is not None:
+ cancel_blocktimestamp = (
+ local_tz.localize(_delivery.cancel_blocktimestamp)
+ .astimezone(tz=UTC)
+ .isoformat()
+ )
+ else:
+ cancel_blocktimestamp = None
+ if _delivery.confirm_blocktimestamp is not None:
+ confirm_blocktimestamp = (
+ local_tz.localize(_delivery.confirm_blocktimestamp)
+ .astimezone(tz=UTC)
+ .isoformat()
+ )
+ else:
+ confirm_blocktimestamp = None
+ if _delivery.finish_blocktimestamp is not None:
+ finish_blocktimestamp = (
+ local_tz.localize(_delivery.finish_blocktimestamp)
+ .astimezone(tz=UTC)
+ .isoformat()
+ )
+ else:
+ finish_blocktimestamp = None
+ if _delivery.abort_blocktimestamp is not None:
+ abort_blocktimestamp = (
+ local_tz.localize(_delivery.abort_blocktimestamp)
+ .astimezone(tz=UTC)
+ .isoformat()
+ )
+ else:
+ abort_blocktimestamp = None
+
+ return json_response(
+ {
+ "exchange_address": _delivery.exchange_address,
+ "delivery_id": _delivery.delivery_id,
+ "token_address": _delivery.token_address,
+ "buyer_address": _delivery.buyer_address,
+ "seller_address": _delivery.seller_address,
+ "amount": _delivery.amount,
+ "agent_address": _delivery.agent_address,
+ "data": _delivery.data,
+ "create_blocktimestamp": create_blocktimestamp,
+ "create_transaction_hash": _delivery.create_transaction_hash,
+ "cancel_blocktimestamp": cancel_blocktimestamp,
+ "cancel_transaction_hash": _delivery.cancel_transaction_hash,
+ "confirm_blocktimestamp": confirm_blocktimestamp,
+ "confirm_transaction_hash": _delivery.confirm_transaction_hash,
+ "finish_blocktimestamp": finish_blocktimestamp,
+ "finish_transaction_hash": _delivery.finish_transaction_hash,
+ "abort_blocktimestamp": abort_blocktimestamp,
+ "abort_transaction_hash": _delivery.abort_transaction_hash,
+ "confirmed": _delivery.confirmed,
+ "valid": _delivery.valid,
+ "status": _delivery.status,
+ }
+ )
+
+
+# POST: /settlement/dvp/{exchange_address}/delivery/{delivery_id}
+@router.post(
+ "/dvp/{exchange_address}/delivery/{delivery_id}",
+ operation_id="UpdateDVPDelivery",
+ response_model=None,
+ responses=get_routers_responses(
+ 404, 422, InvalidParameterError, SendTransactionError
+ ),
+)
+async def update_dvp_delivery(
+ db: DBAsyncSession,
+ req: Request,
+ exchange_address: str,
+ delivery_id: str,
+ data: CancelDVPDeliveryRequest | FinishDVPDeliveryRequest | AbortDVPDeliveryRequest,
+ issuer_address: Optional[str] = Header(None),
+ eoa_password: Optional[str] = Header(None),
+ auth_token: Optional[str] = Header(None),
+):
+ match data.operation_type:
+ case "Cancel":
+ # Validate Headers
+ validate_headers(
+ issuer_address=(issuer_address, address_is_valid_address),
+ eoa_password=(eoa_password, eoa_password_is_encrypted_value),
+ )
+
+ # Authentication
+ _account, decrypt_password = await check_auth(
+ request=req,
+ db=db,
+ issuer_address=issuer_address,
+ eoa_password=eoa_password,
+ auth_token=auth_token,
+ )
+
+ # Get private key
+ keyfile_json = _account.keyfile
+ private_key = decode_keyfile_json(
+ raw_keyfile_json=keyfile_json, password=decrypt_password.encode("utf-8")
+ )
+
+ # Cancel delivery
+ dvp_contract = IbetSecurityTokenDVP(contract_address=exchange_address)
+ try:
+ _data = {"delivery_id": delivery_id}
+ await dvp_contract.cancel_delivery(
+ data=CancelDeliveryParams(**_data),
+ tx_from=issuer_address,
+ private_key=private_key,
+ )
+ except SendTransactionError:
+ raise SendTransactionError("failed to cancel delivery")
+ return
+
+ case "Finish":
+ # Search for agent account
+ agent_account: DVPAgentAccount | None = (
+ await db.scalars(
+ select(DVPAgentAccount)
+ .where(DVPAgentAccount.account_address == data.account_address)
+ .limit(1)
+ )
+ ).first()
+ if agent_account is None:
+ raise HTTPException(
+ status_code=404, detail="agent account is not exists"
+ )
+
+ # Authentication
+ eoa_password = (
+ E2EEUtils.decrypt(data.eoa_password)
+ if E2EE_REQUEST_ENABLED
+ else data.eoa_password
+ )
+ correct_eoa_pass = E2EEUtils.decrypt(agent_account.eoa_password)
+ if eoa_password != correct_eoa_pass:
+ raise InvalidParameterError("password mismatch")
+
+ # Get private key
+ keyfile_json = agent_account.keyfile
+ private_key = decode_keyfile_json(
+ raw_keyfile_json=keyfile_json, password=correct_eoa_pass.encode("utf-8")
+ )
+
+ # Cancel delivery
+ dvp_contract = IbetSecurityTokenDVP(contract_address=exchange_address)
+ try:
+ _data = {"delivery_id": delivery_id}
+ await dvp_contract.finish_delivery(
+ data=FinishDeliveryParams(**_data),
+ tx_from=agent_account.account_address,
+ private_key=private_key,
+ )
+ except SendTransactionError:
+ raise SendTransactionError("failed to finish delivery")
+ return
+
+ case "Abort":
+ # Search for agent account
+ agent_account: DVPAgentAccount | None = (
+ await db.scalars(
+ select(DVPAgentAccount)
+ .where(DVPAgentAccount.account_address == data.account_address)
+ .limit(1)
+ )
+ ).first()
+ if agent_account is None:
+ raise HTTPException(
+ status_code=404, detail="agent account is not exists"
+ )
+
+ # Authentication
+ eoa_password = (
+ E2EEUtils.decrypt(data.eoa_password)
+ if E2EE_REQUEST_ENABLED
+ else data.eoa_password
+ )
+ correct_eoa_pass = E2EEUtils.decrypt(agent_account.eoa_password)
+ if eoa_password != correct_eoa_pass:
+ raise InvalidParameterError("password mismatch")
+
+ # Get private key
+ keyfile_json = agent_account.keyfile
+ private_key = decode_keyfile_json(
+ raw_keyfile_json=keyfile_json, password=correct_eoa_pass.encode("utf-8")
+ )
+
+ # Cancel delivery
+ dvp_contract = IbetSecurityTokenDVP(contract_address=exchange_address)
+ try:
+ _data = {"delivery_id": delivery_id}
+ await dvp_contract.abort_delivery(
+ data=AbortDeliveryParams(**_data),
+ tx_from=agent_account.account_address,
+ private_key=private_key,
+ )
+ except SendTransactionError:
+ raise SendTransactionError("failed to abort delivery")
+ return
diff --git a/app/routers/share.py b/app/routers/share.py
index b3bcc35b..c3229614 100644
--- a/app/routers/share.py
+++ b/app/routers/share.py
@@ -18,14 +18,14 @@
"""
import uuid
-from datetime import datetime
+from datetime import UTC, datetime
from decimal import Decimal
from typing import List, Optional, Sequence
+import pytz
from eth_keyfile import decode_keyfile_json
from fastapi import APIRouter, Depends, Header, Query, Request
from fastapi.exceptions import HTTPException
-from pytz import timezone
from sqlalchemy import (
String,
and_,
@@ -42,6 +42,7 @@
select,
)
from sqlalchemy.orm import aliased
+from sqlalchemy.sql.functions import coalesce
import config
from app import log
@@ -51,6 +52,7 @@
ContractRevertError,
InvalidParameterError,
OperationNotAllowedStateError,
+ OperationNotSupportedVersionError,
SendTransactionError,
)
from app.model.blockchain import (
@@ -169,8 +171,8 @@
)
LOG = log.get_logger()
-local_tz = timezone(config.TZ)
-utc_tz = timezone("UTC")
+local_tz = pytz.timezone(config.TZ)
+utc_tz = pytz.timezone("UTC")
# POST: /share/tokens
@@ -246,6 +248,7 @@ async def issue_token(
update_items = [
"tradable_exchange_contract_address",
"personal_info_contract_address",
+ "require_personal_info_registered",
"transferable",
"status",
"is_offering",
@@ -304,7 +307,9 @@ async def issue_token(
_utxo.token_address = contract_address
_utxo.amount = token.total_supply
_utxo.block_number = block["number"]
- _utxo.block_timestamp = datetime.utcfromtimestamp(block["timestamp"])
+ _utxo.block_timestamp = datetime.fromtimestamp(block["timestamp"], UTC).replace(
+ tzinfo=None
+ )
db.add(_utxo)
token_status = 1 # succeeded
@@ -317,7 +322,7 @@ async def issue_token(
_token.token_address = contract_address
_token.abi = abi
_token.token_status = token_status
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# Register operation log
@@ -372,7 +377,7 @@ async def list_all_tokens(
for token in tokens:
# Get contract data
share_token = (await IbetShareContract(token.token_address).get()).__dict__
- issue_datetime_utc = timezone("UTC").localize(token.created)
+ issue_datetime_utc = pytz.timezone("UTC").localize(token.created)
share_token["issue_datetime"] = issue_datetime_utc.astimezone(
local_tz
).isoformat()
@@ -413,7 +418,7 @@ async def retrieve_token(db: DBAsyncSession, token_address: str):
# Get contract data
share_token = (await IbetShareContract(token_address).get()).__dict__
- issue_datetime_utc = timezone("UTC").localize(_token.created)
+ issue_datetime_utc = pytz.timezone("UTC").localize(_token.created)
share_token["issue_datetime"] = issue_datetime_utc.astimezone(local_tz).isoformat()
share_token["token_status"] = _token.token_status
share_token["contract_version"] = _token.version
@@ -434,13 +439,14 @@ async def retrieve_token(db: DBAsyncSession, token_address: str):
InvalidParameterError,
SendTransactionError,
ContractRevertError,
+ OperationNotSupportedVersionError,
),
)
async def update_token(
db: DBAsyncSession,
request: Request,
token_address: str,
- token: IbetShareUpdate,
+ update_data: IbetShareUpdate,
issuer_address: str = Header(...),
eoa_password: Optional[str] = Header(None),
auth_token: Optional[str] = Header(None),
@@ -488,12 +494,19 @@ async def update_token(
if _token.token_status == 0:
raise InvalidParameterError("this token is temporarily unavailable")
+ # Verify that the token version supports the operation
+ if _token.version < TokenVersion.V_24_06:
+ if update_data.require_personal_info_registered is not None:
+ raise OperationNotSupportedVersionError(
+ f"the operation is not supported in {_token.version}"
+ )
+
# Send transaction
try:
token_contract = IbetShareContract(token_address)
original_contents = (await token_contract.get()).__dict__
await token_contract.update(
- data=UpdateParams(**token.model_dump()),
+ data=UpdateParams(**update_data.model_dump()),
tx_from=issuer_address,
private_key=private_key,
)
@@ -505,7 +518,7 @@ async def update_token(
operation_log.token_address = token_address
operation_log.issuer_address = issuer_address
operation_log.type = TokenType.IBET_SHARE.value
- operation_log.arguments = token.model_dump(exclude_none=True)
+ operation_log.arguments = update_data.model_dump(exclude_none=True)
operation_log.original_contents = original_contents
operation_log.operation_category = TokenUpdateOperationCategory.UPDATE.value
db.add(operation_log)
@@ -546,14 +559,20 @@ async def list_share_operation_log_history(
)
)
if request_query.created_from:
+ _created_from = datetime.strptime(
+ request_query.created_from + ".000000", "%Y-%m-%d %H:%M:%S.%f"
+ )
stmt = stmt.where(
TokenUpdateOperationLog.created
- >= local_tz.localize(request_query.created_from).astimezone(utc_tz)
+ >= local_tz.localize(_created_from).astimezone(utc_tz)
)
if request_query.created_to:
+ _created_to = datetime.strptime(
+ request_query.created_to + ".999999", "%Y-%m-%d %H:%M:%S.%f"
+ )
stmt = stmt.where(
TokenUpdateOperationLog.created
- <= local_tz.localize(request_query.created_to).astimezone(utc_tz)
+ <= local_tz.localize(_created_to).astimezone(utc_tz)
)
count = await db.scalar(select(func.count()).select_from(stmt.subquery()))
@@ -663,7 +682,7 @@ async def list_additional_issuance_history(
history = []
for _event in _events:
- block_timestamp_utc = timezone("UTC").localize(_event.block_timestamp)
+ block_timestamp_utc = pytz.timezone("UTC").localize(_event.block_timestamp)
history.append(
{
"transaction_hash": _event.transaction_hash,
@@ -779,11 +798,6 @@ async def list_all_additional_issue_upload(
get_query: ListAllAdditionalIssueUploadQuery = Depends(),
issuer_address: Optional[str] = Header(None),
):
- processed = get_query.processed
- sort_order = get_query.sort_order
- offset = get_query.offset
- limit = get_query.limit
-
# Get a list of uploads
stmt = select(BatchIssueRedeemUpload).where(
and_(
@@ -798,28 +812,28 @@ async def list_all_additional_issue_upload(
total = await db.scalar(select(func.count()).select_from(stmt.subquery()))
- if processed is not None:
- stmt = stmt.where(BatchIssueRedeemUpload.processed == processed)
+ if get_query.processed is not None:
+ stmt = stmt.where(BatchIssueRedeemUpload.processed == get_query.processed)
count = await db.scalar(select(func.count()).select_from(stmt.subquery()))
# Sort
- if sort_order == 0: # ASC
+ if get_query.sort_order == 0: # ASC
stmt = stmt.order_by(BatchIssueRedeemUpload.created)
else: # DESC
stmt = stmt.order_by(desc(BatchIssueRedeemUpload.created))
# Pagination
- if limit is not None:
- stmt = stmt.limit(limit)
- if offset is not None:
- stmt = stmt.offset(offset)
+ if get_query.limit is not None:
+ stmt = stmt.limit(get_query.limit)
+ if get_query.offset is not None:
+ stmt = stmt.offset(get_query.offset)
_upload_list: Sequence[BatchIssueRedeemUpload] = (await db.scalars(stmt)).all()
uploads = []
for _upload in _upload_list:
- created_utc = timezone("UTC").localize(_upload.created)
+ created_utc = pytz.timezone("UTC").localize(_upload.created)
uploads.append(
{
"batch_id": _upload.upload_id,
@@ -834,8 +848,8 @@ async def list_all_additional_issue_upload(
resp = {
"result_set": {
"count": count,
- "offset": offset,
- "limit": limit,
+ "offset": get_query.offset,
+ "limit": get_query.limit,
"total": total,
},
"uploads": uploads,
@@ -1025,11 +1039,6 @@ async def list_redeem_history(
get_query: ListRedeemHistoryQuery = Depends(),
):
"""List redemption history"""
- sort_item = get_query.sort_item
- sort_order = get_query.sort_order
- offset = get_query.offset
- limit = get_query.limit
-
# Get token
_token: Token | None = (
await db.scalars(
@@ -1060,26 +1069,26 @@ async def list_redeem_history(
count = total
# Sort
- sort_attr = getattr(IDXIssueRedeem, sort_item.value, None)
- if sort_order == 0: # ASC
+ sort_attr = getattr(IDXIssueRedeem, get_query.sort_item.value, None)
+ if get_query.sort_order == 0: # ASC
stmt = stmt.order_by(sort_attr)
else: # DESC
stmt = stmt.order_by(desc(sort_attr))
- if sort_item != IDXIssueRedeemSortItem.BLOCK_TIMESTAMP:
+ if get_query.sort_item != IDXIssueRedeemSortItem.BLOCK_TIMESTAMP:
# NOTE: Set secondary sort for consistent results
stmt = stmt.order_by(desc(IDXIssueRedeem.block_timestamp))
# Pagination
- if limit is not None:
- stmt = stmt.limit(limit)
- if offset is not None:
- stmt = stmt.offset(offset)
+ if get_query.limit is not None:
+ stmt = stmt.limit(get_query.limit)
+ if get_query.offset is not None:
+ stmt = stmt.offset(get_query.offset)
_events: Sequence[IDXIssueRedeem] = (await db.scalars(stmt)).all()
history = []
for _event in _events:
- block_timestamp_utc = timezone("UTC").localize(_event.block_timestamp)
+ block_timestamp_utc = pytz.timezone("UTC").localize(_event.block_timestamp)
history.append(
{
"transaction_hash": _event.transaction_hash,
@@ -1095,8 +1104,8 @@ async def list_redeem_history(
{
"result_set": {
"count": count,
- "offset": offset,
- "limit": limit,
+ "offset": get_query.offset,
+ "limit": get_query.limit,
"total": total,
},
"history": history,
@@ -1195,10 +1204,6 @@ async def list_all_redeem_upload(
get_query: ListAllRedeemUploadQuery = Depends(),
issuer_address: Optional[str] = Header(None),
):
- processed = get_query.processed
- sort_order = get_query.sort_order
- offset = get_query.offset
- limit = get_query.limit
# Get a list of uploads
stmt = select(BatchIssueRedeemUpload).where(
@@ -1215,28 +1220,28 @@ async def list_all_redeem_upload(
total = await db.scalar(select(func.count()).select_from(stmt.subquery()))
- if processed is not None:
- stmt = stmt.where(BatchIssueRedeemUpload.processed == processed)
+ if get_query.processed is not None:
+ stmt = stmt.where(BatchIssueRedeemUpload.processed == get_query.processed)
count = await db.scalar(select(func.count()).select_from(stmt.subquery()))
# Sort
- if sort_order == 0: # ASC
+ if get_query.sort_order == 0: # ASC
stmt = stmt.order_by(BatchIssueRedeemUpload.created)
else: # DESC
stmt = stmt.order_by(desc(BatchIssueRedeemUpload.created))
# Pagination
- if limit is not None:
- stmt = stmt.limit(limit)
- if offset is not None:
- stmt = stmt.offset(offset)
+ if get_query.limit is not None:
+ stmt = stmt.limit(get_query.limit)
+ if get_query.offset is not None:
+ stmt = stmt.offset(get_query.offset)
_upload_list: Sequence[BatchIssueRedeemUpload] = (await db.scalars(stmt)).all()
uploads = []
for _upload in _upload_list:
- created_utc = timezone("UTC").localize(_upload.created)
+ created_utc = pytz.timezone("UTC").localize(_upload.created)
uploads.append(
{
"batch_id": _upload.upload_id,
@@ -1251,8 +1256,8 @@ async def list_all_redeem_upload(
resp = {
"result_set": {
"count": count,
- "offset": offset,
- "limit": limit,
+ "offset": get_query.offset,
+ "limit": get_query.limit,
"total": total,
},
"uploads": uploads,
@@ -1472,10 +1477,10 @@ async def list_all_scheduled_events(
token_events = []
for _token_event in _token_events:
- scheduled_datetime_utc = timezone("UTC").localize(
+ scheduled_datetime_utc = pytz.timezone("UTC").localize(
_token_event.scheduled_datetime
)
- created_utc = timezone("UTC").localize(_token_event.created)
+ created_utc = pytz.timezone("UTC").localize(_token_event.created)
token_events.append(
{
"scheduled_event_id": _token_event.event_id,
@@ -1498,7 +1503,12 @@ async def list_all_scheduled_events(
"/tokens/{token_address}/scheduled_events",
response_model=ScheduledEventIdResponse,
responses=get_routers_responses(
- 422, 401, 404, AuthorizationError, InvalidParameterError
+ 422,
+ 401,
+ 404,
+ AuthorizationError,
+ InvalidParameterError,
+ OperationNotSupportedVersionError,
),
)
async def schedule_new_update_event(
@@ -1547,6 +1557,13 @@ async def schedule_new_update_event(
if _token.token_status == 0:
raise InvalidParameterError("this token is temporarily unavailable")
+ # Verify that the token version supports the operation
+ if _token.version < TokenVersion.V_24_06:
+ if event_data.data.require_personal_info_registered is not None:
+ raise OperationNotSupportedVersionError(
+ f"the operation is not supported in {_token.version}"
+ )
+
# Register an event
_scheduled_event = ScheduledEvents()
_scheduled_event.event_id = str(uuid.uuid4())
@@ -1610,8 +1627,10 @@ async def retrieve_token_event(
if _token_event is None:
raise HTTPException(status_code=404, detail="event not found")
- scheduled_datetime_utc = timezone("UTC").localize(_token_event.scheduled_datetime)
- created_utc = timezone("UTC").localize(_token_event.created)
+ scheduled_datetime_utc = pytz.timezone("UTC").localize(
+ _token_event.scheduled_datetime
+ )
+ created_utc = pytz.timezone("UTC").localize(_token_event.created)
return json_response(
{
"scheduled_event_id": _token_event.event_id,
@@ -1678,8 +1697,10 @@ async def delete_scheduled_event(
if _token_event is None:
raise HTTPException(status_code=404, detail="event not found")
- scheduled_datetime_utc = timezone("UTC").localize(_token_event.scheduled_datetime)
- created_utc = timezone("UTC").localize(_token_event.created)
+ scheduled_datetime_utc = pytz.timezone("UTC").localize(
+ _token_event.scheduled_datetime
+ )
+ created_utc = pytz.timezone("UTC").localize(_token_event.created)
rtn = {
"scheduled_event_id": _token_event.event_id,
"token_address": token_address,
@@ -1710,21 +1731,6 @@ async def list_all_holders(
issuer_address: str = Header(...),
):
"""List all share token holders"""
- include_former_holder = get_query.include_former_holder
- balance = get_query.balance
- balance_operator = get_query.balance_operator
- pending_transfer = get_query.pending_transfer
- pending_transfer_operator = get_query.pending_transfer_operator
- locked = get_query.locked
- locked_operator = get_query.locked_operator
- account_address = get_query.account_address
- holder_name = get_query.holder_name
- key_manager = get_query.key_manager
- sort_item = get_query.sort_item
- sort_order = get_query.sort_order
- offset = get_query.offset
- limit = get_query.limit
-
# Validate Headers
validate_headers(issuer_address=(issuer_address, address_is_valid_address))
@@ -1791,7 +1797,7 @@ async def list_all_holders(
total = await db.scalar(select(func.count()).select_from(stmt.subquery()))
- if not include_former_holder:
+ if not get_query.include_former_holder:
stmt = stmt.where(
or_(
IDXPosition.balance != 0,
@@ -1802,75 +1808,109 @@ async def list_all_holders(
)
)
- if balance is not None and balance_operator is not None:
- match balance_operator:
+ if get_query.balance is not None and get_query.balance_operator is not None:
+ match get_query.balance_operator:
case ValueOperator.EQUAL:
- stmt = stmt.where(IDXPosition.balance == balance)
+ stmt = stmt.where(IDXPosition.balance == get_query.balance)
case ValueOperator.GTE:
- stmt = stmt.where(IDXPosition.balance >= balance)
+ stmt = stmt.where(IDXPosition.balance >= get_query.balance)
case ValueOperator.LTE:
- stmt = stmt.where(IDXPosition.balance <= balance)
+ stmt = stmt.where(IDXPosition.balance <= get_query.balance)
- if pending_transfer is not None and pending_transfer_operator is not None:
- match pending_transfer_operator:
+ if (
+ get_query.pending_transfer is not None
+ and get_query.pending_transfer_operator is not None
+ ):
+ match get_query.pending_transfer_operator:
case ValueOperator.EQUAL:
- stmt = stmt.where(IDXPosition.pending_transfer == pending_transfer)
+ stmt = stmt.where(
+ IDXPosition.pending_transfer == get_query.pending_transfer
+ )
case ValueOperator.GTE:
- stmt = stmt.where(IDXPosition.pending_transfer >= pending_transfer)
+ stmt = stmt.where(
+ IDXPosition.pending_transfer >= get_query.pending_transfer
+ )
case ValueOperator.LTE:
- stmt = stmt.where(IDXPosition.pending_transfer <= pending_transfer)
+ stmt = stmt.where(
+ IDXPosition.pending_transfer <= get_query.pending_transfer
+ )
- if locked is not None and locked_operator is not None:
- match locked_operator:
+ if get_query.locked is not None and get_query.locked_operator is not None:
+ match get_query.locked_operator:
case ValueOperator.EQUAL:
- stmt = stmt.having(locked_value == locked)
+ stmt = stmt.having(coalesce(locked_value, 0) == get_query.locked)
case ValueOperator.GTE:
- stmt = stmt.having(locked_value >= locked)
+ stmt = stmt.having(coalesce(locked_value, 0) >= get_query.locked)
case ValueOperator.LTE:
- stmt = stmt.having(locked_value <= locked)
+ stmt = stmt.having(coalesce(locked_value, 0) <= get_query.locked)
- if account_address is not None:
- stmt = stmt.where(IDXPosition.account_address.like("%" + account_address + "%"))
+ if (
+ get_query.balance_and_pending_transfer is not None
+ and get_query.balance_and_pending_transfer_operator is not None
+ ):
+ match get_query.balance_and_pending_transfer_operator:
+ case ValueOperator.EQUAL:
+ stmt = stmt.where(
+ IDXPosition.balance + IDXPosition.pending_transfer
+ == get_query.balance_and_pending_transfer
+ )
+ case ValueOperator.GTE:
+ stmt = stmt.where(
+ IDXPosition.balance + IDXPosition.pending_transfer
+ >= get_query.balance_and_pending_transfer
+ )
+ case ValueOperator.LTE:
+ stmt = stmt.where(
+ IDXPosition.balance + IDXPosition.pending_transfer
+ <= get_query.balance_and_pending_transfer
+ )
- if holder_name is not None:
+ if get_query.account_address is not None:
+ stmt = stmt.where(
+ IDXPosition.account_address.like("%" + get_query.account_address + "%")
+ )
+
+ if get_query.holder_name is not None:
stmt = stmt.where(
IDXPersonalInfo._personal_info["name"]
.as_string()
- .like("%" + holder_name + "%")
+ .like("%" + get_query.holder_name + "%")
)
- if key_manager is not None:
+ if get_query.key_manager is not None:
stmt = stmt.where(
IDXPersonalInfo._personal_info["key_manager"]
.as_string()
- .like("%" + key_manager + "%")
+ .like("%" + get_query.key_manager + "%")
)
count = await db.scalar(select(func.count()).select_from(stmt.subquery()))
# Sort
- if sort_item == ListAllHoldersSortItem.holder_name:
+ if get_query.sort_item == ListAllHoldersSortItem.holder_name:
sort_attr = IDXPersonalInfo._personal_info["name"].as_string()
- elif sort_item == ListAllHoldersSortItem.key_manager:
+ elif get_query.sort_item == ListAllHoldersSortItem.key_manager:
sort_attr = IDXPersonalInfo._personal_info["key_manager"].as_string()
- elif sort_item == ListAllHoldersSortItem.locked:
+ elif get_query.sort_item == ListAllHoldersSortItem.locked:
sort_attr = locked_value
+ elif get_query.sort_item == ListAllHoldersSortItem.balance_and_pending_transfer:
+ sort_attr = IDXPosition.balance + IDXPosition.pending_transfer
else:
- sort_attr = getattr(IDXPosition, sort_item)
+ sort_attr = getattr(IDXPosition, get_query.sort_item)
- if sort_order == 0: # ASC
+ if get_query.sort_order == 0: # ASC
stmt = stmt.order_by(asc(sort_attr))
else: # DESC
stmt = stmt.order_by(desc(sort_attr))
- if sort_item != ListAllHoldersSortItem.created:
+ if get_query.sort_item != ListAllHoldersSortItem.created:
# NOTE: Set secondary sort for consistent results
stmt = stmt.order_by(asc(IDXPosition.created))
# Pagination
- if limit is not None:
- stmt = stmt.limit(limit)
- if offset is not None:
- stmt = stmt.offset(offset)
+ if get_query.limit is not None:
+ stmt = stmt.limit(get_query.limit)
+ if get_query.offset is not None:
+ stmt = stmt.offset(get_query.offset)
_holders: Sequence[
tuple[IDXPosition, int, IDXPersonalInfo | None, datetime | None]
@@ -1923,8 +1963,8 @@ async def list_all_holders(
"result_set": {
"count": count,
"total": total,
- "limit": limit,
- "offset": offset,
+ "limit": get_query.limit,
+ "offset": get_query.offset,
},
"holders": holders,
}
@@ -2248,11 +2288,6 @@ async def list_all_personal_info_batch_registration_uploads(
get_query: ListAllPersonalInfoBatchRegistrationUploadQuery = Depends(),
):
"""List all personal information batch registration uploads"""
- status = get_query.status
- sort_order = get_query.sort_order
- offset = get_query.offset
- limit = get_query.limit
-
# Verify that the token is issued by the issuer_address
_token: Token | None = (
await db.scalars(
@@ -2280,22 +2315,22 @@ async def list_all_personal_info_batch_registration_uploads(
total = await db.scalar(select(func.count()).select_from(stmt.subquery()))
- if status is not None:
- stmt = stmt.where(BatchRegisterPersonalInfoUpload.status == status)
+ if get_query.status is not None:
+ stmt = stmt.where(BatchRegisterPersonalInfoUpload.status == get_query.status)
count = await db.scalar(select(func.count()).select_from(stmt.subquery()))
# Sort
- if sort_order == 0: # ASC
+ if get_query.sort_order == 0: # ASC
stmt = stmt.order_by(BatchRegisterPersonalInfoUpload.created)
else: # DESC
stmt = stmt.order_by(desc(BatchRegisterPersonalInfoUpload.created))
# Pagination
- if limit is not None:
- stmt = stmt.limit(limit)
- if offset is not None:
- stmt = stmt.offset(offset)
+ if get_query.limit is not None:
+ stmt = stmt.limit(get_query.limit)
+ if get_query.offset is not None:
+ stmt = stmt.offset(get_query.offset)
_upload_list: Sequence[BatchRegisterPersonalInfoUpload] = (
await db.scalars(stmt)
@@ -2303,7 +2338,7 @@ async def list_all_personal_info_batch_registration_uploads(
uploads = []
for _upload in _upload_list:
- created_utc = timezone("UTC").localize(_upload.created)
+ created_utc = pytz.timezone("UTC").localize(_upload.created)
uploads.append(
{
"batch_id": _upload.upload_id,
@@ -2316,8 +2351,8 @@ async def list_all_personal_info_batch_registration_uploads(
{
"result_set": {
"count": count,
- "offset": offset,
- "limit": limit,
+ "offset": get_query.offset,
+ "limit": get_query.limit,
"total": total,
},
"uploads": uploads,
@@ -2403,7 +2438,7 @@ async def batch_register_personal_info(
{
"batch_id": batch_id,
"status": batch.status,
- "created": timezone("UTC")
+ "created": pytz.timezone("UTC")
.localize(batch.created)
.astimezone(local_tz)
.isoformat(),
@@ -2631,7 +2666,7 @@ async def list_all_lock_events_by_share(
for lock_event in lock_events:
token: Token = lock_event.Token
share_contract = await IbetShareContract(token.token_address).get()
- block_timestamp_utc = timezone("UTC").localize(lock_event.block_timestamp)
+ block_timestamp_utc = pytz.timezone("UTC").localize(lock_event.block_timestamp)
resp_data.append(
{
"category": lock_event.category,
@@ -2748,10 +2783,10 @@ async def transfer_ownership(
async def list_transfer_history(
db: DBAsyncSession,
token_address: str,
- request_query: ListTransferHistoryQuery = Depends(),
+ query: ListTransferHistoryQuery = Depends(),
):
"""List token transfer history"""
- # Get token
+ # Check if the token has been issued
_token: Token | None = (
await db.scalars(
select(Token)
@@ -2792,33 +2827,71 @@ async def list_transfer_history(
)
.where(IDXTransfer.token_address == token_address)
)
-
total = await db.scalar(select(func.count()).select_from(stmt.subquery()))
- if request_query.source_event is not None:
- stmt = stmt.where(IDXTransfer.source_event == request_query.source_event)
- if request_query.data is not None:
+ # Filter
+ if query.block_timestamp_from is not None:
stmt = stmt.where(
- cast(IDXTransfer.data, String).like("%" + request_query.data + "%")
+ IDXTransfer.block_timestamp
+ >= local_tz.localize(query.block_timestamp_from).astimezone(UTC)
)
-
+ if query.block_timestamp_to is not None:
+ stmt = stmt.where(
+ IDXTransfer.block_timestamp
+ <= local_tz.localize(query.block_timestamp_to).astimezone(UTC)
+ )
+ if query.from_address is not None:
+ stmt = stmt.where(IDXTransfer.from_address == query.from_address)
+ if query.to_address is not None:
+ stmt = stmt.where(IDXTransfer.to_address == query.to_address)
+ if query.from_address_name:
+ stmt = stmt.where(
+ from_address_personal_info._personal_info["name"]
+ .as_string()
+ .like("%" + query.from_address_name + "%")
+ )
+ if query.to_address_name:
+ stmt = stmt.where(
+ to_address_personal_info._personal_info["name"]
+ .as_string()
+ .like("%" + query.to_address_name + "%")
+ )
+ if query.amount is not None and query.amount_operator is not None:
+ match query.amount_operator:
+ case ValueOperator.EQUAL:
+ stmt = stmt.where(IDXTransfer.amount == query.amount)
+ case ValueOperator.GTE:
+ stmt = stmt.where(IDXTransfer.amount >= query.amount)
+ case ValueOperator.LTE:
+ stmt = stmt.where(IDXTransfer.amount <= query.amount)
+ if query.source_event is not None:
+ stmt = stmt.where(IDXTransfer.source_event == query.source_event)
+ if query.data is not None:
+ stmt = stmt.where(cast(IDXTransfer.data, String).like("%" + query.data + "%"))
count = await db.scalar(select(func.count()).select_from(stmt.subquery()))
# Sort
- sort_attr = getattr(IDXTransfer, request_query.sort_item.value, None)
- if request_query.sort_order == 0: # ASC
+ match query.sort_item:
+ case ListTransferHistorySortItem.FROM_ADDRESS_NAME:
+ sort_attr = from_address_personal_info._personal_info["name"].as_string()
+ case ListTransferHistorySortItem.TO_ADDRESS_NAME:
+ sort_attr = to_address_personal_info._personal_info["name"].as_string()
+ case _:
+ sort_attr = getattr(IDXTransfer, query.sort_item.value, None)
+
+ if query.sort_order == 0: # ASC
stmt = stmt.order_by(sort_attr)
else: # DESC
stmt = stmt.order_by(desc(sort_attr))
- if request_query.sort_item != ListTransferHistorySortItem.BLOCK_TIMESTAMP:
+ if query.sort_item != ListTransferHistorySortItem.BLOCK_TIMESTAMP:
# NOTE: Set secondary sort for consistent results
stmt = stmt.order_by(desc(IDXTransfer.block_timestamp))
# Pagination
- if request_query.limit is not None:
- stmt = stmt.limit(request_query.limit)
- if request_query.offset is not None:
- stmt = stmt.offset(request_query.offset)
+ if query.limit is not None:
+ stmt = stmt.limit(query.limit)
+ if query.offset is not None:
+ stmt = stmt.offset(query.offset)
_transfers: Sequence[
tuple[IDXTransfer, IDXPersonalInfo | None, IDXPersonalInfo | None]
@@ -2826,7 +2899,7 @@ async def list_transfer_history(
transfer_history = []
for _transfer, _from_address_personal_info, _to_address_personal_info in _transfers:
- block_timestamp_utc = timezone("UTC").localize(_transfer.block_timestamp)
+ block_timestamp_utc = pytz.timezone("UTC").localize(_transfer.block_timestamp)
transfer_history.append(
{
"transaction_hash": _transfer.transaction_hash,
@@ -2854,8 +2927,8 @@ async def list_transfer_history(
{
"result_set": {
"count": count,
- "offset": request_query.offset,
- "limit": request_query.limit,
+ "offset": query.offset,
+ "limit": query.limit,
"total": total,
},
"transfer_history": transfer_history,
@@ -3010,14 +3083,6 @@ async def list_token_transfer_approval_history(
get_query: ListTransferApprovalHistoryQuery = Depends(),
):
"""List token transfer approval history"""
- from_address = get_query.from_address
- to_address = get_query.to_address
- status = get_query.status
- sort_item = get_query.sort_item
- sort_order = get_query.sort_order
- offset = get_query.offset
- limit = get_query.limit
-
# Get token
_token: Token | None = (
await db.scalars(
@@ -3134,33 +3199,33 @@ async def list_token_transfer_approval_history(
total = await db.scalar(select(func.count()).select_from(stmt.subquery()))
# Search Filter
- if from_address is not None:
- stmt = stmt.where(subquery.from_address == from_address)
- if to_address is not None:
- stmt = stmt.where(subquery.to_address == to_address)
- if status is not None:
- stmt = stmt.where(literal_column("status").in_(status))
+ if get_query.from_address is not None:
+ stmt = stmt.where(subquery.from_address == get_query.from_address)
+ if get_query.to_address is not None:
+ stmt = stmt.where(subquery.to_address == get_query.to_address)
+ if get_query.status is not None:
+ stmt = stmt.where(literal_column("status").in_(get_query.status))
count = await db.scalar(select(func.count()).select_from(stmt.subquery()))
# Sort
- if sort_item != IDXTransferApprovalsSortItem.STATUS:
- sort_attr = getattr(subquery, sort_item, None)
+ if get_query.sort_item != IDXTransferApprovalsSortItem.STATUS:
+ sort_attr = getattr(subquery, get_query.sort_item, None)
else:
sort_attr = literal_column("status")
- if sort_order == 0: # ASC
+ if get_query.sort_order == 0: # ASC
stmt = stmt.order_by(sort_attr)
else: # DESC
stmt = stmt.order_by(desc(sort_attr))
- if sort_item != IDXTransferApprovalsSortItem.ID:
+ if get_query.sort_item != IDXTransferApprovalsSortItem.ID:
# NOTE: Set secondary sort for consistent results
stmt = stmt.order_by(desc(subquery.id))
# Pagination
- if limit is not None:
- stmt = stmt.limit(limit)
- if offset is not None:
- stmt = stmt.offset(offset)
+ if get_query.limit is not None:
+ stmt = stmt.limit(get_query.limit)
+ if get_query.offset is not None:
+ stmt = stmt.offset(get_query.offset)
_transfer_approvals: Sequence[
tuple[
@@ -3202,12 +3267,12 @@ async def list_token_transfer_approval_history(
else:
issuer_cancelable = True
- application_datetime_utc = timezone("UTC").localize(
+ application_datetime_utc = pytz.timezone("UTC").localize(
_transfer_approval.application_datetime
)
application_datetime = application_datetime_utc.astimezone(local_tz).isoformat()
- application_blocktimestamp_utc = timezone("UTC").localize(
+ application_blocktimestamp_utc = pytz.timezone("UTC").localize(
_transfer_approval.application_blocktimestamp
)
application_blocktimestamp = application_blocktimestamp_utc.astimezone(
@@ -3215,7 +3280,7 @@ async def list_token_transfer_approval_history(
).isoformat()
if _transfer_approval.approval_datetime is not None:
- approval_datetime_utc = timezone("UTC").localize(
+ approval_datetime_utc = pytz.timezone("UTC").localize(
_transfer_approval.approval_datetime
)
approval_datetime = approval_datetime_utc.astimezone(local_tz).isoformat()
@@ -3223,7 +3288,7 @@ async def list_token_transfer_approval_history(
approval_datetime = None
if _transfer_approval.approval_blocktimestamp is not None:
- approval_blocktimestamp_utc = timezone("UTC").localize(
+ approval_blocktimestamp_utc = pytz.timezone("UTC").localize(
_transfer_approval.approval_blocktimestamp
)
approval_blocktimestamp = approval_blocktimestamp_utc.astimezone(
@@ -3233,7 +3298,7 @@ async def list_token_transfer_approval_history(
approval_blocktimestamp = None
if _transfer_approval.cancellation_blocktimestamp is not None:
- cancellation_blocktimestamp_utc = timezone("UTC").localize(
+ cancellation_blocktimestamp_utc = pytz.timezone("UTC").localize(
_transfer_approval.cancellation_blocktimestamp
)
cancellation_blocktimestamp = cancellation_blocktimestamp_utc.astimezone(
@@ -3288,8 +3353,8 @@ async def list_token_transfer_approval_history(
{
"result_set": {
"count": count,
- "offset": offset,
- "limit": limit,
+ "offset": get_query.offset,
+ "limit": get_query.limit,
"total": total,
},
"transfer_approval_history": transfer_approval_history,
@@ -3456,7 +3521,7 @@ async def update_transfer_approval(
# a cancelTransfer is performed immediately.
# - CANCEL -> cancelTransfer
try:
- now = str(datetime.utcnow().timestamp())
+ now = str(datetime.now(UTC).replace(tzinfo=None).timestamp())
if data.operation_type == UpdateTransferApprovalOperationType.APPROVE:
if _transfer_approval.exchange_address == config.ZERO_ADDRESS:
_data = {
@@ -3643,12 +3708,12 @@ async def retrieve_transfer_approval_history(
else:
issuer_cancelable = True
- application_datetime_utc = timezone("UTC").localize(
+ application_datetime_utc = pytz.timezone("UTC").localize(
_transfer_approval.application_datetime
)
application_datetime = application_datetime_utc.astimezone(local_tz).isoformat()
- application_blocktimestamp_utc = timezone("UTC").localize(
+ application_blocktimestamp_utc = pytz.timezone("UTC").localize(
_transfer_approval.application_blocktimestamp
)
application_blocktimestamp = application_blocktimestamp_utc.astimezone(
@@ -3656,7 +3721,7 @@ async def retrieve_transfer_approval_history(
).isoformat()
if _transfer_approval.approval_datetime is not None:
- approval_datetime_utc = timezone("UTC").localize(
+ approval_datetime_utc = pytz.timezone("UTC").localize(
_transfer_approval.approval_datetime
)
approval_datetime = approval_datetime_utc.astimezone(local_tz).isoformat()
@@ -3664,7 +3729,7 @@ async def retrieve_transfer_approval_history(
approval_datetime = None
if _transfer_approval.approval_blocktimestamp is not None:
- approval_blocktimestamp_utc = timezone("UTC").localize(
+ approval_blocktimestamp_utc = pytz.timezone("UTC").localize(
_transfer_approval.approval_blocktimestamp
)
approval_blocktimestamp = approval_blocktimestamp_utc.astimezone(
@@ -3674,7 +3739,7 @@ async def retrieve_transfer_approval_history(
approval_blocktimestamp = None
if _transfer_approval.cancellation_blocktimestamp is not None:
- cancellation_blocktimestamp_utc = timezone("UTC").localize(
+ cancellation_blocktimestamp_utc = pytz.timezone("UTC").localize(
_transfer_approval.cancellation_blocktimestamp
)
cancellation_blocktimestamp = cancellation_blocktimestamp_utc.astimezone(
@@ -3910,7 +3975,7 @@ async def list_bulk_transfer_upload(
uploads = []
for _upload in _uploads:
- created_utc = timezone("UTC").localize(_upload.created)
+ created_utc = pytz.timezone("UTC").localize(_upload.created)
uploads.append(
{
"issuer_address": _upload.issuer_address,
diff --git a/app/routers/token_holders.py b/app/routers/token_holders.py
index 58a73e6e..6359a612 100644
--- a/app/routers/token_holders.py
+++ b/app/routers/token_holders.py
@@ -18,16 +18,20 @@
"""
import uuid
+from datetime import datetime
from typing import Optional, Sequence
+import pytz
from fastapi import APIRouter, Depends, Header, Path, Query
from fastapi.exceptions import HTTPException
from sqlalchemy import and_, asc, desc, func, select
+import config
from app.database import DBAsyncSession
from app.exceptions import InvalidParameterError
from app.model.db import (
IDXPersonalInfo,
+ IDXPersonalInfoHistory,
Token,
TokenHolder,
TokenHolderBatchStatus,
@@ -37,6 +41,8 @@
CreateTokenHoldersListRequest,
CreateTokenHoldersListResponse,
ListAllTokenHolderCollectionsResponse,
+ ListTokenHoldersPersonalInfoHistoryQuery,
+ ListTokenHoldersPersonalInfoHistoryResponse,
ListTokenHoldersPersonalInfoQuery,
ListTokenHoldersPersonalInfoResponse,
RetrieveTokenHoldersListResponse,
@@ -52,45 +58,85 @@
prefix="/token",
tags=["token_common"],
)
+local_tz = pytz.timezone(config.TZ)
+utc_tz = pytz.timezone("UTC")
# GET: /token/holders/personal_info
@router.get(
"/holders/personal_info",
+ operation_id="ListTokenHoldersPersonalInfo",
response_model=ListTokenHoldersPersonalInfoResponse,
responses=get_routers_responses(422),
)
async def list_all_token_holders_personal_info(
db: DBAsyncSession,
issuer_address: str = Header(...),
- request_query: ListTokenHoldersPersonalInfoQuery = Depends(),
+ get_query: ListTokenHoldersPersonalInfoQuery = Depends(),
):
"""Lists the personal information of all registered holders linked to the token issuer"""
+
# Validate Headers
validate_headers(issuer_address=(issuer_address, address_is_valid_address))
- offset = request_query.offset
- limit = request_query.limit
- sort_order = request_query.sort_order # default: asc
-
+ # Get all data
stmt = select(IDXPersonalInfo).where(
IDXPersonalInfo.issuer_address == issuer_address
)
total = await db.scalar(select(func.count()).select_from(stmt.subquery()))
+ # Filter
+ if get_query.account_address:
+ stmt = stmt.where(IDXPersonalInfo.account_address == get_query.account_address)
+ if get_query.created_from:
+ _created_from = datetime.strptime(
+ get_query.created_from + ".000000", "%Y-%m-%d %H:%M:%S.%f"
+ )
+ stmt = stmt.where(
+ IDXPersonalInfo.created
+ >= local_tz.localize(_created_from).astimezone(utc_tz)
+ )
+ if get_query.created_to:
+ _created_to = datetime.strptime(
+ get_query.created_to + ".999999", "%Y-%m-%d %H:%M:%S.%f"
+ )
+ stmt = stmt.where(
+ IDXPersonalInfo.created <= local_tz.localize(_created_to).astimezone(utc_tz)
+ )
+ if get_query.modified_from:
+ _modified_from = datetime.strptime(
+ get_query.modified_from + ".000000", "%Y-%m-%d %H:%M:%S.%f"
+ )
+ stmt = stmt.where(
+ IDXPersonalInfo.modified
+ >= local_tz.localize(_modified_from).astimezone(utc_tz)
+ )
+ if get_query.modified_to:
+ _modified_to = datetime.strptime(
+ get_query.modified_to + ".999999", "%Y-%m-%d %H:%M:%S.%f"
+ )
+ stmt = stmt.where(
+ IDXPersonalInfo.modified
+ <= local_tz.localize(_modified_to).astimezone(utc_tz)
+ )
+
count = await db.scalar(select(func.count()).select_from(stmt.subquery()))
# Sort
- if sort_order == 0:
+ sort_attr = getattr(IDXPersonalInfo, get_query.sort_item, None)
+ if get_query.sort_order == 0: # ASC
+ stmt = stmt.order_by(sort_attr)
+ else: # DESC
+ stmt = stmt.order_by(desc(sort_attr))
+ if get_query.sort_item != IDXPersonalInfo.created:
+ # NOTE: Set secondary sort for consistent results
stmt = stmt.order_by(IDXPersonalInfo.created)
- else:
- stmt = stmt.order_by(desc(IDXPersonalInfo.created))
# Pagination
- if limit is not None:
- stmt = stmt.limit(limit)
- if offset is not None:
- stmt = stmt.offset(offset)
+ if get_query.limit is not None:
+ stmt = stmt.limit(get_query.limit)
+ if get_query.offset is not None:
+ stmt = stmt.offset(get_query.offset)
personal_info_list: Sequence[IDXPersonalInfo] = (await db.scalars(stmt)).all()
data = [_personal_info.json() for _personal_info in personal_info_list]
@@ -99,8 +145,101 @@ async def list_all_token_holders_personal_info(
{
"result_set": {
"count": count,
- "offset": offset,
- "limit": limit,
+ "offset": get_query.offset,
+ "limit": get_query.limit,
+ "total": total,
+ },
+ "personal_info": data,
+ },
+ )
+
+
+# GET: /token/holders/personal_info/history
+@router.get(
+ "/holders/personal_info/history",
+ operation_id="ListTokenHoldersPersonalInfoHistory",
+ response_model=ListTokenHoldersPersonalInfoHistoryResponse,
+ responses=get_routers_responses(422),
+)
+async def list_all_token_holders_personal_info_history(
+ db: DBAsyncSession,
+ issuer_address: str = Header(...),
+ get_query: ListTokenHoldersPersonalInfoHistoryQuery = Depends(),
+):
+ """List personal information historical data"""
+
+ # Validate Headers
+ validate_headers(issuer_address=(issuer_address, address_is_valid_address))
+
+ # Get all data
+ stmt = select(IDXPersonalInfoHistory).where(
+ IDXPersonalInfoHistory.issuer_address == issuer_address
+ )
+ total = await db.scalar(select(func.count()).select_from(stmt.subquery()))
+
+ # Filter
+ if get_query.account_address is not None:
+ stmt = stmt.where(
+ IDXPersonalInfoHistory.account_address == get_query.account_address
+ )
+ if get_query.event_type is not None:
+ stmt = stmt.where(IDXPersonalInfoHistory.event_type == get_query.event_type)
+ if get_query.block_timestamp_from:
+ _block_timestamp_from = datetime.strptime(
+ get_query.block_timestamp_from + ".000000", "%Y-%m-%d %H:%M:%S.%f"
+ )
+ stmt = stmt.where(
+ IDXPersonalInfoHistory.block_timestamp
+ >= local_tz.localize(_block_timestamp_from).astimezone(utc_tz)
+ )
+ if get_query.block_timestamp_to:
+ _block_timestamp_to = datetime.strptime(
+ get_query.block_timestamp_to + ".999999", "%Y-%m-%d %H:%M:%S.%f"
+ )
+ stmt = stmt.where(
+ IDXPersonalInfoHistory.block_timestamp
+ <= local_tz.localize(_block_timestamp_to).astimezone(utc_tz)
+ )
+ if get_query.created_from:
+ _created_from = datetime.strptime(
+ get_query.created_from + ".000000", "%Y-%m-%d %H:%M:%S.%f"
+ )
+ stmt = stmt.where(
+ IDXPersonalInfoHistory.created
+ >= local_tz.localize(_created_from).astimezone(utc_tz)
+ )
+ if get_query.created_to:
+ _created_to = datetime.strptime(
+ get_query.created_to + ".999999", "%Y-%m-%d %H:%M:%S.%f"
+ )
+ stmt = stmt.where(
+ IDXPersonalInfoHistory.created
+ <= local_tz.localize(_created_to).astimezone(utc_tz)
+ )
+
+ count = await db.scalar(select(func.count()).select_from(stmt.subquery()))
+
+ # Sort
+ if get_query.sort_order == 0:
+ stmt = stmt.order_by(IDXPersonalInfoHistory.block_timestamp)
+ else:
+ stmt = stmt.order_by(desc(IDXPersonalInfoHistory.block_timestamp))
+
+ # Pagination
+ if get_query.limit is not None:
+ stmt = stmt.limit(get_query.limit)
+ if get_query.offset is not None:
+ stmt = stmt.offset(get_query.offset)
+
+ history_list: Sequence[IDXPersonalInfoHistory] = (await db.scalars(stmt)).all()
+ data = [_history.json() for _history in history_list]
+
+ return json_response(
+ {
+ "result_set": {
+ "count": count,
+ "offset": get_query.offset,
+ "limit": get_query.limit,
"total": total,
},
"personal_info": data,
diff --git a/app/utils/check_utils.py b/app/utils/check_utils.py
index 88b22e85..9fbb3be9 100644
--- a/app/utils/check_utils.py
+++ b/app/utils/check_utils.py
@@ -18,7 +18,7 @@
"""
import hashlib
-from datetime import datetime, timedelta
+from datetime import UTC, datetime, timedelta
from typing import Optional
from fastapi import Request
@@ -192,10 +192,7 @@ async def check_token_for_auth(db: AsyncSession, issuer_address: str, auth_token
hashed_token = hashlib.sha256(auth_token.encode()).hexdigest()
if issuer_token.auth_token != hashed_token:
raise AuthorizationError
- elif (
- issuer_token.valid_duration != 0
- and issuer_token.usage_start
- + timedelta(seconds=issuer_token.valid_duration)
- < datetime.utcnow()
- ):
+ elif issuer_token.valid_duration != 0 and issuer_token.usage_start + timedelta(
+ seconds=issuer_token.valid_duration
+ ) < datetime.now(UTC).replace(tzinfo=None):
raise AuthorizationError
diff --git a/app/utils/contract_error_code.py b/app/utils/contract_error_code.py
index 56ec0539..27ec004f 100644
--- a/app/utils/contract_error_code.py
+++ b/app/utils/contract_error_code.py
@@ -157,6 +157,34 @@
240303: "Message sender is not escrow agent.",
240304: "Token status of escrow is inactive.",
240401: "Message sender balance is insufficient.",
+ # DVPStorage (25XXXX)
+ 250001: "Message sender(exchange contract) isn't latest version.",
+ # IbetSecurityTokenDVP (26XXXX)
+ 260001: "Delivery amount is 0.",
+ 260002: "Message sender balance is insufficient.",
+ 260003: "Token status of delivery is inactive.",
+ 260004: "Token transferApprovalRequired of delivery is enabled.",
+ 260101: "Target delivery ID is invalid.",
+ 260102: "Target delivery status is invalid.",
+ 260103: "Target delivery has been confirmed.",
+ 260104: "Message sender is not the delivery seller nor the delivery buyer.",
+ 260201: "Target delivery ID is invalid.",
+ 260202: "Target delivery status is invalid.",
+ 260203: "Target delivery has been confirmed.",
+ 260204: "Message sender is not the delivery buyer.",
+ 260205: "Token status of delivery is inactive.",
+ 260206: "Token transferApprovalRequired of delivery is enabled.",
+ 260301: "Target delivery ID is invalid.",
+ 260302: "Target delivery status is invalid.",
+ 260303: "Target delivery has not been confirmed.",
+ 260304: "Message sender is not the delivery agent.",
+ 260305: "Token status of delivery is inactive.",
+ 260306: "Token transferApprovalRequired of delivery is enabled.",
+ 260401: "Target delivery ID is invalid.",
+ 260402: "Target delivery status is invalid.",
+ 260403: "Target delivery has been confirmed.",
+ 260404: "Message sender is not the delivery agent.",
+ 260501: "Message sender balance is insufficient.",
# PaymentGateway (30XXXX)
300001: "Payment account is banned.",
300101: "Target account address is not registered.",
diff --git a/app/utils/contract_utils.py b/app/utils/contract_utils.py
index fc867742..91fb7f1f 100644
--- a/app/utils/contract_utils.py
+++ b/app/utils/contract_utils.py
@@ -202,13 +202,15 @@ def send_transaction(transaction: dict, private_key: bytes):
transaction_dict=transaction, private_key=private_key
)
# Send Transaction
- tx_hash = web3.eth.send_raw_transaction(signed_tx.rawTransaction.hex())
+ tx_hash = web3.eth.send_raw_transaction(
+ signed_tx.raw_transaction.to_0x_hex()
+ )
tx_receipt = web3.eth.wait_for_transaction_receipt(
transaction_hash=tx_hash, timeout=10
)
if tx_receipt["status"] == 0:
# inspect reason of transaction fail
- code_msg = ContractUtils.inspect_tx_failure(tx_hash.hex())
+ code_msg = ContractUtils.inspect_tx_failure(tx_hash.to_0x_hex())
raise ContractRevertError(code_msg=code_msg)
except:
raise
@@ -216,7 +218,7 @@ def send_transaction(transaction: dict, private_key: bytes):
local_session.rollback() # unlock record
local_session.close()
- return tx_hash.hex(), tx_receipt
+ return tx_hash.to_0x_hex(), tx_receipt
@staticmethod
def inspect_tx_failure(tx_hash: str) -> str:
@@ -268,16 +270,16 @@ def get_event_logs(
:param contract: Contract
:param event: Event
- :param block_from: fromBlock
- :param block_to: toBlock
+ :param block_from: from_block
+ :param block_to: to_block
:param argument_filters: Argument filter
:return: Event logs
"""
try:
_event = getattr(contract.events, event)
result = _event.get_logs(
- fromBlock=block_from,
- toBlock=block_to,
+ from_block=block_from,
+ to_block=block_to,
argument_filters=argument_filters,
)
except ABIEventFunctionNotFound:
@@ -455,14 +457,16 @@ async def send_transaction(transaction: dict, private_key: bytes):
)
# Send Transaction
tx_hash = await async_web3.eth.send_raw_transaction(
- signed_tx.rawTransaction.hex()
+ signed_tx.raw_transaction.to_0x_hex()
)
tx_receipt = await async_web3.eth.wait_for_transaction_receipt(
transaction_hash=tx_hash, timeout=10
)
if tx_receipt["status"] == 0:
# inspect reason of transaction fail
- code_msg = await AsyncContractUtils.inspect_tx_failure(tx_hash.hex())
+ code_msg = await AsyncContractUtils.inspect_tx_failure(
+ tx_hash.to_0x_hex()
+ )
raise ContractRevertError(code_msg=code_msg)
except:
raise
@@ -470,7 +474,7 @@ async def send_transaction(transaction: dict, private_key: bytes):
await local_session.rollback() # unlock record
await local_session.close()
- return tx_hash.hex(), tx_receipt
+ return tx_hash.to_0x_hex(), tx_receipt
@staticmethod
async def inspect_tx_failure(tx_hash: str) -> str:
@@ -522,16 +526,16 @@ async def get_event_logs(
:param contract: Contract
:param event: Event
- :param block_from: fromBlock
- :param block_to: toBlock
+ :param block_from: from_block
+ :param block_to: to_block
:param argument_filters: Argument filter
:return: Event logs
"""
try:
_event = getattr(contract.events, event)
result = await _event.get_logs(
- fromBlock=block_from,
- toBlock=block_to,
+ from_block=block_from,
+ to_block=block_to,
argument_filters=argument_filters,
)
except ABIEventFunctionNotFound:
diff --git a/app/utils/e2ee_utils.py b/app/utils/e2ee_utils.py
index 5708da63..e34cb9fd 100644
--- a/app/utils/e2ee_utils.py
+++ b/app/utils/e2ee_utils.py
@@ -19,7 +19,7 @@
import base64
import binascii
-from datetime import datetime, timedelta
+from datetime import UTC, datetime, timedelta
import boto3
from Crypto.Cipher import PKCS1_OAEP
@@ -118,7 +118,9 @@ def __get_crypto_data() -> DictCache:
)
# Use Cache
- if E2EEUtils.cache.get("expiration_datetime") > datetime.utcnow():
+ if E2EEUtils.cache.get("expiration_datetime") > datetime.now(UTC).replace(
+ tzinfo=None
+ ):
return E2EEUtils.cache
# Get Private Key
@@ -148,7 +150,8 @@ def __get_crypto_data() -> DictCache:
"private_key": private_key,
"public_key": public_key,
"encrypted_length": encrypted_length,
- "expiration_datetime": datetime.utcnow() + timedelta(hours=1),
+ "expiration_datetime": datetime.now(UTC).replace(tzinfo=None)
+ + timedelta(hours=1),
}
)
diff --git a/app/utils/ledger_utils.py b/app/utils/ledger_utils.py
index e94371ba..3c4a0f8e 100644
--- a/app/utils/ledger_utils.py
+++ b/app/utils/ledger_utils.py
@@ -18,7 +18,7 @@
"""
import uuid
-from datetime import datetime
+from datetime import UTC, datetime
from typing import Sequence
import pytz
@@ -26,6 +26,7 @@
from sqlalchemy.ext.asyncio import AsyncSession
from app.model.blockchain import (
+ ContractPersonalInfoType,
IbetShareContract,
IbetStraightBondContract,
PersonalInfoContract,
@@ -93,21 +94,22 @@ async def create_ledger(token_address: str, db: AsyncSession):
for _details in _details_list:
# Get ledger details data
- data_list = await __get_details_data_list(
+ data_list, some_personal_info_not_registered = await __get_details_data_list(
token_address, _token.type, _details.data_type, _details.data_source, db
)
-
- # NOTE: Merge with template with ledger GET API
details = {
"token_detail_type": _details.token_detail_type,
"headers": _details.headers,
"data": data_list,
"footers": _details.footers,
+ "some_personal_info_not_registered": some_personal_info_not_registered,
}
ledger_details.append(details)
created_ymd = (
- utc_tz.localize(datetime.utcnow()).astimezone(local_tz).strftime("%Y/%m/%d")
+ utc_tz.localize(datetime.now(UTC).replace(tzinfo=None))
+ .astimezone(local_tz)
+ .strftime("%Y/%m/%d")
)
# NOTE: Merge with template with ledger GET API
ledger = {
@@ -153,8 +155,9 @@ async def __get_details_data_list(
data_type: str,
data_source: str,
db: AsyncSession,
-):
+) -> tuple[list[dict], bool]:
data_list = []
+ some_personal_info_not_registered = False
if data_type == LedgerDetailsDataType.DB.value:
data_list = []
# Get Ledger Details Data from DB
@@ -183,16 +186,19 @@ async def __get_details_data_list(
}
)
elif data_type == LedgerDetailsDataType.IBET_FIN.value:
- data_list = await __get_details_data_list_from_ibetfin(
- token_address, token_type, db
+ # NOTE:
+ # If there is an account with no personal information registered,
+ # some_personal_info_not_registered will be True.
+ data_list, some_personal_info_not_registered = (
+ await __get_details_data_list_from_ibetfin(token_address, token_type, db)
)
- return data_list
+ return data_list, some_personal_info_not_registered
async def __get_details_data_list_from_ibetfin(
token_address: str, token_type: str, db: AsyncSession
-):
+) -> tuple[list[dict], bool]:
if token_type == TokenType.IBET_SHARE.value:
token_contract = await IbetShareContract(token_address).get()
price = token_contract.principal_value
@@ -245,6 +251,7 @@ async def __get_details_data_list_from_ibetfin(
utxo_grouped[_utxo.account_address][date_ymd] += _utxo.amount
data_list = []
+ some_personal_info_not_registered = False
for account_address, date_ymd_amount in utxo_grouped.items():
for date_ymd, amount in date_ymd_amount.items():
details_data = {
@@ -258,9 +265,9 @@ async def __get_details_data_list_from_ibetfin(
}
# Update PersonalInfo
- personal_info = await __get_personal_info(
+ personal_info, _pi_not_registered = await __get_personal_info(
account_address,
- token_contract.issuer_address,
+ token_contract,
personal_info_contract,
db,
)
@@ -268,34 +275,71 @@ async def __get_details_data_list_from_ibetfin(
details_data["address"] = personal_info.get("address", None)
data_list.append(details_data)
+ if _pi_not_registered:
+ some_personal_info_not_registered = True
- return data_list
+ return data_list, some_personal_info_not_registered
async def __get_personal_info(
account_address: str,
- issuer_address: str,
+ token_contract: IbetShareContract | IbetStraightBondContract,
personal_info_contract: PersonalInfoContract,
db: AsyncSession,
-):
+) -> tuple[dict, bool]:
+ # NOTE:
+ # For tokens with require_personal_info_registered = False, search only indexed data.
+ # If indexed data does not exist, return the default value.
+
+ # Issuer cannot have any personal info
+ if account_address == token_contract.issuer_address:
+ personal_info_not_registered = False
+ return (
+ ContractPersonalInfoType(
+ key_manager=None,
+ name=None,
+ address=None,
+ postal_code=None,
+ email=None,
+ birth=None,
+ ).model_dump(),
+ personal_info_not_registered,
+ )
+
+ # Search indexed data
_idx_personal_info: IDXPersonalInfo | None = (
await db.scalars(
select(IDXPersonalInfo)
.where(
and_(
IDXPersonalInfo.account_address == account_address,
- IDXPersonalInfo.issuer_address == issuer_address,
+ IDXPersonalInfo.issuer_address == token_contract.issuer_address,
)
)
.limit(1)
)
).first()
+ if (
+ _idx_personal_info is not None
+ and any(_idx_personal_info.personal_info.values()) is not False
+ ):
+ # Get personal info from DB
+ personal_info_not_registered = False
+ return _idx_personal_info.personal_info, personal_info_not_registered
- if _idx_personal_info is None: # Get PersonalInfo to Contract
+ # Retrieve personal info
+ if token_contract.require_personal_info_registered is True:
+ # Retrieve from contract storage
personal_info = await personal_info_contract.get_info(
account_address, default_value=None
)
+ if any(personal_info.values()) is False:
+ personal_info_not_registered = True
+ else:
+ personal_info_not_registered = False
else:
- personal_info = _idx_personal_info.personal_info
+ # Do not retrieve contract data and return the default value
+ personal_info = ContractPersonalInfoType().model_dump()
+ personal_info_not_registered = True
- return personal_info
+ return personal_info, personal_info_not_registered
diff --git a/app/utils/web3_utils.py b/app/utils/web3_utils.py
index 379e39e6..32b1e78c 100644
--- a/app/utils/web3_utils.py
+++ b/app/utils/web3_utils.py
@@ -30,10 +30,10 @@
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import Session
-from web3 import AsyncWeb3, Web3
+from web3 import AsyncHTTPProvider, AsyncWeb3, HTTPProvider, Web3
from web3.eth import AsyncEth
from web3.geth import AsyncGeth
-from web3.middleware import async_geth_poa_middleware, geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
from web3.net import AsyncNet
from web3.types import RPCEndpoint, RPCResponse
@@ -77,7 +77,7 @@ def _get_web3(request_timeout: int) -> Web3:
web3 = Web3(
FailOverHTTPProvider(request_kwargs={"timeout": request_timeout})
)
- web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+ web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
thread_local.web3 = web3
return web3
@@ -115,13 +115,13 @@ def _get_web3(request_timeout: int) -> AsyncWeb3:
async_web3 = AsyncWeb3(
AsyncFailOverHTTPProvider(request_kwargs={"timeout": request_timeout})
)
- async_web3.middleware_onion.inject(async_geth_poa_middleware, layer=0)
+ async_web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
thread_local.async_web3 = async_web3
return async_web3
-class FailOverHTTPProvider(Web3.HTTPProvider):
+class FailOverHTTPProvider(HTTPProvider):
fail_over_mode = False # If False, use only the default(primary) provider
def __init__(self, *args, **kwargs):
@@ -180,7 +180,7 @@ def set_fail_over_mode(use_fail_over: bool):
FailOverHTTPProvider.fail_over_mode = use_fail_over
-class AsyncFailOverHTTPProvider(Web3.AsyncHTTPProvider):
+class AsyncFailOverHTTPProvider(AsyncHTTPProvider):
fail_over_mode = False # If False, use only the default(primary) provider
def __init__(self, *args, **kwargs):
diff --git a/batch/indexer_block_tx_data.py b/batch/indexer_block_tx_data.py
index 2fce52e7..ccfc72da 100644
--- a/batch/indexer_block_tx_data.py
+++ b/batch/indexer_block_tx_data.py
@@ -68,23 +68,25 @@ async def process(self):
# Synchronize block data
block_model = IDXBlockData()
block_model.number = block_data.get("number")
- block_model.parent_hash = block_data.get("parentHash").hex()
- block_model.sha3_uncles = block_data.get("sha3Uncles").hex()
+ block_model.parent_hash = block_data.get("parentHash").to_0x_hex()
+ block_model.sha3_uncles = block_data.get("sha3Uncles").to_0x_hex()
block_model.miner = block_data.get("miner")
- block_model.state_root = block_data.get("stateRoot").hex()
- block_model.transactions_root = block_data.get("transactionsRoot").hex()
- block_model.receipts_root = block_data.get("receiptsRoot").hex()
- block_model.logs_bloom = block_data.get("logsBloom").hex()
+ block_model.state_root = block_data.get("stateRoot").to_0x_hex()
+ block_model.transactions_root = block_data.get(
+ "transactionsRoot"
+ ).to_0x_hex()
+ block_model.receipts_root = block_data.get("receiptsRoot").to_0x_hex()
+ block_model.logs_bloom = block_data.get("logsBloom").to_0x_hex()
block_model.difficulty = block_data.get("difficulty")
block_model.gas_limit = block_data.get("gasLimit")
block_model.gas_used = block_data.get("gasUsed")
block_model.timestamp = block_data.get("timestamp")
block_model.proof_of_authority_data = block_data.get(
"proofOfAuthorityData"
- ).hex()
- block_model.mix_hash = block_data.get("mixHash").hex()
- block_model.nonce = block_data.get("nonce").hex()
- block_model.hash = block_data.get("hash").hex()
+ ).to_0x_hex()
+ block_model.mix_hash = block_data.get("mixHash").to_0x_hex()
+ block_model.nonce = block_data.get("nonce").to_0x_hex()
+ block_model.hash = block_data.get("hash").to_0x_hex()
block_model.size = block_data.get("size")
transactions: Sequence[TxData] = block_data.get("transactions")
@@ -92,8 +94,8 @@ async def process(self):
for transaction in transactions:
# Synchronize tx data
tx_model = IDXTxData()
- tx_model.hash = transaction.get("hash").hex()
- tx_model.block_hash = transaction.get("blockHash").hex()
+ tx_model.hash = transaction.get("hash").to_0x_hex()
+ tx_model.block_hash = transaction.get("blockHash").to_0x_hex()
tx_model.block_number = transaction.get("blockNumber")
tx_model.transaction_index = transaction.get("transactionIndex")
tx_model.from_address = to_checksum_address(transaction.get("from"))
@@ -102,14 +104,14 @@ async def process(self):
if transaction.get("to")
else None
)
- tx_model.input = transaction.get("input").hex()
+ tx_model.input = transaction.get("input").to_0x_hex()
tx_model.gas = transaction.get("gas")
tx_model.gas_price = transaction.get("gasPrice")
tx_model.value = transaction.get("value")
tx_model.nonce = transaction.get("nonce")
local_session.add(tx_model)
- transaction_hash_list.append(transaction.get("hash").hex())
+ transaction_hash_list.append(transaction.get("hash").to_0x_hex())
block_model.transactions = transaction_hash_list
local_session.add(block_model)
diff --git a/batch/indexer_delivery.py b/batch/indexer_delivery.py
new file mode 100644
index 00000000..a3b1be72
--- /dev/null
+++ b/batch/indexer_delivery.py
@@ -0,0 +1,597 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+import asyncio
+import sys
+from datetime import UTC, datetime
+from typing import Literal, Optional, Sequence
+
+import uvloop
+from sqlalchemy import and_, select
+from sqlalchemy.exc import SQLAlchemyError
+from sqlalchemy.ext.asyncio import AsyncSession
+from web3.contract import AsyncContract
+
+from app.database import BatchAsyncSessionLocal
+from app.exceptions import ServiceUnavailableError
+from app.model.blockchain import IbetShareContract, IbetStraightBondContract
+from app.model.db import (
+ Account,
+ DeliveryStatus,
+ IDXDelivery,
+ IDXDeliveryBlockNumber,
+ Token,
+ TokenType,
+)
+from app.utils.contract_utils import AsyncContractUtils
+from app.utils.web3_utils import AsyncWeb3Wrapper
+from batch import batch_log
+from config import INDEXER_BLOCK_LOT_MAX_SIZE, INDEXER_SYNC_INTERVAL, ZERO_ADDRESS
+
+process_name = "INDEXER-Delivery"
+LOG = batch_log.get_logger(process_name=process_name)
+
+web3 = AsyncWeb3Wrapper()
+
+
+"""
+Batch process for indexing security token dvp delivery events
+
+ibetSecurityTokenDVP
+ - CreateDelivery
+ - CancelDelivery
+ - ConfirmDelivery
+ - FinishDelivery
+ - AbortDelivery
+"""
+
+
+class Processor:
+ def __init__(self):
+ self.token_list: list[str] = []
+ self.exchange_list: list[AsyncContract] = []
+
+ async def sync_new_logs(self):
+ db_session = BatchAsyncSessionLocal()
+ try:
+ await self.__get_contract_list(db_session=db_session)
+
+ latest_block = await web3.eth.block_number
+ for contract in self.exchange_list:
+ # Get from_block_number and to_block_number for contract event filter
+ _from_block = await self.__get_idx_delivery_block_number(
+ db_session=db_session, exchange_address=contract.address
+ )
+ _to_block = _from_block + INDEXER_BLOCK_LOT_MAX_SIZE
+
+ # Skip processing if the latest block is not counted up
+ if _from_block >= latest_block:
+ LOG.debug("skip process")
+ return
+
+ # Create index data with the upper limit of one process
+ # as INDEXER_BLOCK_LOT_MAX_SIZE(1_000_000 blocks)
+ if latest_block > _to_block:
+ while _to_block < latest_block:
+ await self.__sync_all(
+ db_session=db_session,
+ block_from=_from_block + 1,
+ block_to=_to_block,
+ exchange=contract,
+ )
+ _to_block += INDEXER_BLOCK_LOT_MAX_SIZE
+ _from_block += INDEXER_BLOCK_LOT_MAX_SIZE
+ await self.__sync_all(
+ db_session=db_session,
+ block_from=_from_block + 1,
+ block_to=latest_block,
+ exchange=contract,
+ )
+ else:
+ await self.__sync_all(
+ db_session=db_session,
+ block_from=_from_block + 1,
+ block_to=latest_block,
+ exchange=contract,
+ )
+
+ await self.__set_idx_delivery_block_number(
+ db_session=db_session,
+ exchange_address=contract.address,
+ block_number=latest_block,
+ )
+ await db_session.commit()
+ finally:
+ await db_session.close()
+ LOG.info("Sync job has been completed")
+
+ async def __get_contract_list(self, db_session: AsyncSession):
+ """Get DVP contract list to index delivery event"""
+ issued_token_address_list: tuple[str, ...] = tuple(
+ [
+ record[0]
+ for record in (
+ await db_session.execute(
+ select(Token.token_address)
+ .join(
+ Account,
+ and_(
+ Account.issuer_address == Token.issuer_address,
+ Account.is_deleted == False,
+ ),
+ )
+ .where(Token.token_status == 1)
+ )
+ )
+ .tuples()
+ .all()
+ ]
+ )
+ loaded_exchange_address_list: tuple[str, ...] = tuple(self.token_list)
+ load_required_address_list = list(
+ set(issued_token_address_list) ^ set(loaded_exchange_address_list)
+ )
+
+ load_required_token_list: Sequence[Token] = (
+ await db_session.scalars(
+ select(Token).where(
+ and_(
+ Token.token_status == 1,
+ Token.token_address.in_(load_required_address_list),
+ )
+ )
+ )
+ ).all()
+
+ _exchange_list_tmp = []
+ for load_required_token in load_required_token_list:
+ self.token_list.append(load_required_token.token_address)
+ token_contract = web3.eth.contract(
+ address=load_required_token.token_address, abi=load_required_token.abi
+ )
+ tradable_exchange_address = ZERO_ADDRESS
+ if load_required_token.type == TokenType.IBET_STRAIGHT_BOND.value:
+ bond_token = IbetStraightBondContract(token_contract.address)
+ await bond_token.get()
+ tradable_exchange_address = (
+ bond_token.tradable_exchange_contract_address
+ )
+ elif load_required_token.type == TokenType.IBET_SHARE.value:
+ share_token = IbetShareContract(token_contract.address)
+ await share_token.get()
+ tradable_exchange_address = (
+ share_token.tradable_exchange_contract_address
+ )
+
+ if tradable_exchange_address != ZERO_ADDRESS:
+ _exchange_list_tmp.append(tradable_exchange_address)
+
+ # Remove duplicate exchanges from a list
+ loaded_exchange_address_list: tuple[str, ...] = tuple(
+ [exchange.address for exchange in self.exchange_list]
+ )
+ for _exchange_address in list(set(_exchange_list_tmp)):
+ if _exchange_address not in loaded_exchange_address_list:
+ exchange_contract = AsyncContractUtils.get_contract(
+ contract_name="IbetSecurityTokenDVP",
+ contract_address=_exchange_address,
+ )
+ self.exchange_list.append(exchange_contract)
+
+ @staticmethod
+ async def __get_idx_delivery_block_number(
+ db_session: AsyncSession, exchange_address: str
+ ):
+ """Get block number of delivery index"""
+ _idx_delivery_block_number = (
+ await db_session.scalars(
+ select(IDXDeliveryBlockNumber)
+ .where(IDXDeliveryBlockNumber.exchange_address == exchange_address)
+ .limit(1)
+ )
+ ).first()
+ if _idx_delivery_block_number is None:
+ return 0
+ else:
+ return _idx_delivery_block_number.latest_block_number
+
+ @staticmethod
+ async def __set_idx_delivery_block_number(
+ db_session: AsyncSession,
+ exchange_address: str,
+ block_number: int,
+ ):
+ """Set block number of delivery index"""
+ _idx_delivery_block_number = (
+ await db_session.scalars(
+ select(IDXDeliveryBlockNumber)
+ .where(IDXDeliveryBlockNumber.exchange_address == exchange_address)
+ .limit(1)
+ )
+ ).first()
+ if _idx_delivery_block_number is None:
+ _idx_delivery_block_number = IDXDeliveryBlockNumber()
+ _idx_delivery_block_number.latest_block_number = block_number
+ _idx_delivery_block_number.exchange_address = exchange_address
+ await db_session.merge(_idx_delivery_block_number)
+
+ async def __sync_all(
+ self,
+ db_session: AsyncSession,
+ block_from: int,
+ block_to: int,
+ exchange: AsyncContract,
+ ):
+ LOG.info(
+ f"Syncing from={block_from}, to={block_to}, exchange={exchange.address}"
+ )
+ await self.__sync_delivery_created(
+ db_session, block_from, block_to, exchange=exchange
+ )
+ await self.__sync_delivery_canceled(
+ db_session, block_from, block_to, exchange=exchange
+ )
+ await self.__sync_delivery_confirmed(
+ db_session, block_from, block_to, exchange=exchange
+ )
+ await self.__sync_delivery_finished(
+ db_session, block_from, block_to, exchange=exchange
+ )
+ await self.__sync_delivery_aborted(
+ db_session, block_from, block_to, exchange=exchange
+ )
+
+ async def __sync_delivery_created(
+ self,
+ db_session: AsyncSession,
+ block_from: int,
+ block_to: int,
+ exchange: AsyncContract,
+ ):
+ """Sync DeliveryCreated events of IbetSecurityTokenDVP
+ :param db_session: ORM session
+ :param block_to: To Block
+ :return: None
+ """
+ if block_from > block_to:
+ return
+ try:
+ events = await AsyncContractUtils.get_event_logs(
+ contract=exchange,
+ event="DeliveryCreated",
+ block_from=block_from,
+ block_to=block_to,
+ )
+ for event in events:
+ transaction_hash = event["transactionHash"].to_0x_hex()
+ args = event["args"]
+ amount = args.get("amount", 0)
+ if amount > sys.maxsize: # suppress overflow
+ continue
+ block_timestamp = await self.__get_block_timestamp(event=event)
+ await self.__sink_on_delivery(
+ db_session=db_session,
+ event_type="Created",
+ exchange_address=exchange.address,
+ delivery_id=args.get("deliveryId"),
+ token_address=args.get("token", ZERO_ADDRESS),
+ seller_address=args.get("seller", ZERO_ADDRESS),
+ buyer_address=args.get("buyer", ZERO_ADDRESS),
+ amount=amount,
+ agent_address=args.get("agent", ZERO_ADDRESS),
+ block_timestamp=block_timestamp,
+ transaction_hash=transaction_hash,
+ data=args.get("data"),
+ )
+ except Exception:
+ raise
+
+ async def __sync_delivery_canceled(
+ self,
+ db_session: AsyncSession,
+ block_from: int,
+ block_to: int,
+ exchange: AsyncContract,
+ ):
+ """Sync DeliveryCanceled events of IbetSecurityTokenDVP
+ :param db_session: ORM session
+ :param block_to: To Block
+ :return: None
+ """
+ if block_from > block_to:
+ return
+ try:
+ events = await AsyncContractUtils.get_event_logs(
+ contract=exchange,
+ event="DeliveryCanceled",
+ block_from=block_from,
+ block_to=block_to,
+ )
+ for event in events:
+ transaction_hash = event["transactionHash"].to_0x_hex()
+ args = event["args"]
+ amount = args.get("amount", 0)
+ if amount > sys.maxsize: # suppress overflow
+ continue
+ block_timestamp = await self.__get_block_timestamp(event=event)
+ await self.__sink_on_delivery(
+ db_session=db_session,
+ event_type="Canceled",
+ exchange_address=exchange.address,
+ delivery_id=args.get("deliveryId"),
+ token_address=args.get("token", ZERO_ADDRESS),
+ seller_address=args.get("seller", ZERO_ADDRESS),
+ buyer_address=args.get("buyer", ZERO_ADDRESS),
+ amount=amount,
+ agent_address=args.get("agent", ZERO_ADDRESS),
+ block_timestamp=block_timestamp,
+ transaction_hash=transaction_hash,
+ )
+ except Exception:
+ raise
+
+ async def __sync_delivery_confirmed(
+ self,
+ db_session: AsyncSession,
+ block_from: int,
+ block_to: int,
+ exchange: AsyncContract,
+ ):
+ """Sync DeliveryConfirmed events of IbetSecurityTokenDVP
+ :param db_session: ORM session
+ :param block_to: To Block
+ :return: None
+ """
+ if block_from > block_to:
+ return
+ try:
+ events = await AsyncContractUtils.get_event_logs(
+ contract=exchange,
+ event="DeliveryConfirmed",
+ block_from=block_from,
+ block_to=block_to,
+ )
+ for event in events:
+ transaction_hash = event["transactionHash"].to_0x_hex()
+ args = event["args"]
+ amount = args.get("amount", 0)
+ if amount > sys.maxsize: # suppress overflow
+ continue
+ block_timestamp = await self.__get_block_timestamp(event=event)
+ await self.__sink_on_delivery(
+ db_session=db_session,
+ event_type="Confirmed",
+ exchange_address=exchange.address,
+ delivery_id=args.get("deliveryId"),
+ token_address=args.get("token", ZERO_ADDRESS),
+ seller_address=args.get("seller", ZERO_ADDRESS),
+ buyer_address=args.get("buyer", ZERO_ADDRESS),
+ amount=amount,
+ agent_address=args.get("agent", ZERO_ADDRESS),
+ block_timestamp=block_timestamp,
+ transaction_hash=transaction_hash,
+ )
+ except Exception:
+ raise
+
+ async def __sync_delivery_finished(
+ self,
+ db_session: AsyncSession,
+ block_from: int,
+ block_to: int,
+ exchange: AsyncContract,
+ ):
+ """Sync DeliveryFinished events of IbetSecurityTokenDVP
+ :param db_session: ORM session
+ :param block_to: To Block
+ :return: None
+ """
+ if block_from > block_to:
+ return
+ try:
+ events = await AsyncContractUtils.get_event_logs(
+ contract=exchange,
+ event="DeliveryFinished",
+ block_from=block_from,
+ block_to=block_to,
+ )
+ for event in events:
+ transaction_hash = event["transactionHash"].to_0x_hex()
+ args = event["args"]
+ amount = args.get("amount", 0)
+ if amount > sys.maxsize: # suppress overflow
+ continue
+ block_timestamp = await self.__get_block_timestamp(event=event)
+ await self.__sink_on_delivery(
+ db_session=db_session,
+ event_type="Finished",
+ exchange_address=exchange.address,
+ delivery_id=args.get("deliveryId"),
+ token_address=args.get("token", ZERO_ADDRESS),
+ seller_address=args.get("seller", ZERO_ADDRESS),
+ buyer_address=args.get("buyer", ZERO_ADDRESS),
+ amount=amount,
+ agent_address=args.get("agent", ZERO_ADDRESS),
+ block_timestamp=block_timestamp,
+ transaction_hash=transaction_hash,
+ )
+ except Exception:
+ raise
+
+ async def __sync_delivery_aborted(
+ self,
+ db_session: AsyncSession,
+ block_from: int,
+ block_to: int,
+ exchange: AsyncContract,
+ ):
+ """Sync DeliveryAborted events of IbetSecurityTokenDVP
+ :param db_session: ORM session
+ :param block_to: To Block
+ :return: None
+ """
+ if block_from > block_to:
+ return
+ try:
+ events = await AsyncContractUtils.get_event_logs(
+ contract=exchange,
+ event="DeliveryAborted",
+ block_from=block_from,
+ block_to=block_to,
+ )
+ for event in events:
+ transaction_hash = event["transactionHash"].to_0x_hex()
+ args = event["args"]
+ amount = args.get("amount", 0)
+ if amount > sys.maxsize: # suppress overflow
+ continue
+ block_timestamp = await self.__get_block_timestamp(event=event)
+ await self.__sink_on_delivery(
+ db_session=db_session,
+ event_type="Aborted",
+ exchange_address=exchange.address,
+ delivery_id=args.get("deliveryId"),
+ token_address=args.get("token", ZERO_ADDRESS),
+ seller_address=args.get("seller", ZERO_ADDRESS),
+ buyer_address=args.get("buyer", ZERO_ADDRESS),
+ amount=amount,
+ agent_address=args.get("agent", ZERO_ADDRESS),
+ block_timestamp=block_timestamp,
+ transaction_hash=transaction_hash,
+ )
+ except Exception:
+ raise
+
+ @staticmethod
+ async def __get_block_timestamp(event) -> int:
+ block_timestamp = (await web3.eth.get_block(event["blockNumber"]))["timestamp"]
+ return block_timestamp
+
+ @staticmethod
+ async def __sink_on_delivery(
+ db_session: AsyncSession,
+ event_type: Literal["Created", "Canceled", "Confirmed", "Finished", "Aborted"],
+ exchange_address: str,
+ delivery_id: int,
+ token_address: str,
+ buyer_address: str,
+ seller_address: str,
+ amount: int,
+ agent_address: str,
+ block_timestamp: int,
+ transaction_hash: str,
+ data: Optional[str] = None,
+ ):
+ """Update Delivery data in DB
+ :param db_session: ORM session
+ :param event_type: event type ["Created", "Canceled", "Confirmed", "Finished", "Aborted"]
+ :param token_address: token address
+ :param exchange_address: exchange address
+ :param delivery_id: delivery id
+ :param buyer_address: delivery buyer address
+ :param seller_address: delivery seller address
+ :param amount: delivery amount
+ :param agent_address: delivery agent address
+ :param data: optional data (Created)
+ :param block_timestamp: block timestamp
+ :return: None
+ """
+ delivery = (
+ await db_session.scalars(
+ select(IDXDelivery)
+ .where(IDXDelivery.exchange_address == exchange_address)
+ .where(IDXDelivery.delivery_id == delivery_id)
+ .limit(1)
+ )
+ ).first()
+ if event_type == "Created":
+ if delivery is None:
+ delivery = IDXDelivery()
+ delivery.exchange_address = exchange_address
+ delivery.delivery_id = delivery_id
+ delivery.token_address = token_address
+ delivery.buyer_address = buyer_address
+ delivery.seller_address = seller_address
+ delivery.amount = amount
+ delivery.agent_address = agent_address
+ delivery.data = data
+ delivery.create_blocktimestamp = datetime.fromtimestamp(
+ block_timestamp, tz=UTC
+ )
+ delivery.create_transaction_hash = transaction_hash
+ delivery.confirmed = False
+ delivery.valid = True
+ delivery.status = DeliveryStatus.DELIVERY_CREATED
+ elif event_type == "Canceled":
+ if delivery is not None:
+ delivery.cancel_blocktimestamp = datetime.fromtimestamp(
+ block_timestamp, tz=UTC
+ )
+ delivery.cancel_transaction_hash = transaction_hash
+ delivery.valid = False
+ delivery.status = DeliveryStatus.DELIVERY_CANCELED
+ elif event_type == "Confirmed":
+ if delivery is not None:
+ delivery.confirm_blocktimestamp = datetime.fromtimestamp(
+ block_timestamp, tz=UTC
+ )
+ delivery.confirm_transaction_hash = transaction_hash
+ delivery.confirmed = True
+ delivery.status = DeliveryStatus.DELIVERY_CONFIRMED
+ elif event_type == "Finished":
+ if delivery is not None:
+ delivery.finish_blocktimestamp = datetime.fromtimestamp(
+ block_timestamp, tz=UTC
+ )
+ delivery.finish_transaction_hash = transaction_hash
+ delivery.valid = False
+ delivery.status = DeliveryStatus.DELIVERY_FINISHED
+ elif event_type == "Aborted":
+ if delivery is not None:
+ delivery.abort_blocktimestamp = datetime.fromtimestamp(
+ block_timestamp, tz=UTC
+ )
+ delivery.abort_transaction_hash = transaction_hash
+ delivery.valid = False
+ delivery.status = DeliveryStatus.DELIVERY_ABORTED
+ await db_session.merge(delivery)
+
+
+async def main():
+ LOG.info("Service started successfully")
+ processor = Processor()
+
+ while True:
+ try:
+ await processor.sync_new_logs()
+ except ServiceUnavailableError:
+ LOG.warning("An external service was unavailable")
+ except SQLAlchemyError as sa_err:
+ LOG.error(f"A database error has occurred: code={sa_err.code}\n{sa_err}")
+ except Exception as ex:
+ LOG.error(ex)
+
+ await asyncio.sleep(INDEXER_SYNC_INTERVAL)
+
+
+if __name__ == "__main__":
+ try:
+ uvloop.run(main())
+ except KeyboardInterrupt:
+ sys.exit(1)
diff --git a/batch/indexer_e2e_messaging.py b/batch/indexer_e2e_messaging.py
index 7bf01e8f..aed1cf62 100644
--- a/batch/indexer_e2e_messaging.py
+++ b/batch/indexer_e2e_messaging.py
@@ -22,7 +22,7 @@
import json
import sys
import time
-from datetime import datetime
+from datetime import UTC, datetime
import uvloop
from Crypto.Cipher import AES, PKCS1_OAEP
@@ -172,14 +172,16 @@ async def __sync_message(
block_to=block_to,
)
for event in events:
- transaction_hash = event["transactionHash"].hex()
- block_timestamp = datetime.utcfromtimestamp(
- (await web3.eth.get_block(event["blockNumber"]))["timestamp"]
- )
+ transaction_hash = event["transactionHash"].to_0x_hex()
+ block_timestamp = datetime.fromtimestamp(
+ (await web3.eth.get_block(event["blockNumber"]))["timestamp"], UTC
+ ).replace(tzinfo=None)
args = event["args"]
from_address = args["sender"]
to_address = args["receiver"]
- send_timestamp = datetime.utcfromtimestamp(args["time"])
+ send_timestamp = datetime.fromtimestamp(args["time"], UTC).replace(
+ tzinfo=None
+ )
text = args["text"]
# Check if the message receiver is owned accounts
@@ -211,7 +213,7 @@ async def __sync_message(
block_timestamp=block_timestamp,
)
except Exception as e:
- LOG.error(e)
+ raise
@staticmethod
async def __get_e2e_messaging_account(db_session: AsyncSession, to_address: str):
diff --git a/batch/indexer_issue_redeem.py b/batch/indexer_issue_redeem.py
index 8d3cb717..52079f72 100644
--- a/batch/indexer_issue_redeem.py
+++ b/batch/indexer_issue_redeem.py
@@ -19,7 +19,7 @@
import asyncio
import sys
-from datetime import datetime
+from datetime import UTC, datetime
from typing import Sequence
import uvloop
@@ -197,10 +197,11 @@ async def __sync_issue(
)
for event in events:
args = event["args"]
- transaction_hash = event["transactionHash"].hex()
- block_timestamp = datetime.utcfromtimestamp(
- (await web3.eth.get_block(event["blockNumber"]))["timestamp"]
- )
+ transaction_hash = event["transactionHash"].to_0x_hex()
+ block_timestamp = datetime.fromtimestamp(
+ (await web3.eth.get_block(event["blockNumber"]))["timestamp"],
+ UTC,
+ ).replace(tzinfo=None)
if args["amount"] > sys.maxsize:
pass
else:
@@ -215,7 +216,7 @@ async def __sync_issue(
block_timestamp=block_timestamp,
)
except Exception:
- LOG.exception("An exception occurred during event synchronization")
+ raise
async def __sync_redeem(
self, db_session: AsyncSession, block_from: int, block_to: int
@@ -237,10 +238,11 @@ async def __sync_redeem(
)
for event in events:
args = event["args"]
- transaction_hash = event["transactionHash"].hex()
- block_timestamp = datetime.utcfromtimestamp(
- (await web3.eth.get_block(event["blockNumber"]))["timestamp"]
- )
+ transaction_hash = event["transactionHash"].to_0x_hex()
+ block_timestamp = datetime.fromtimestamp(
+ (await web3.eth.get_block(event["blockNumber"]))["timestamp"],
+ UTC,
+ ).replace(tzinfo=None)
if args["amount"] > sys.maxsize:
pass
else:
@@ -255,7 +257,7 @@ async def __sync_redeem(
block_timestamp=block_timestamp,
)
except Exception:
- LOG.exception("An exception occurred during event synchronization")
+ raise
@staticmethod
async def __insert_index(
diff --git a/batch/indexer_personal_info.py b/batch/indexer_personal_info.py
index cb46bb4b..f16a523b 100644
--- a/batch/indexer_personal_info.py
+++ b/batch/indexer_personal_info.py
@@ -20,7 +20,7 @@
import asyncio
import json
import sys
-from datetime import datetime
+from datetime import UTC, datetime
from typing import Sequence
import uvloop
@@ -40,6 +40,8 @@
Account,
IDXPersonalInfo,
IDXPersonalInfoBlockNumber,
+ IDXPersonalInfoHistory,
+ PersonalInfoEventType,
Token,
TokenType,
)
@@ -203,7 +205,9 @@ async def __sync_personal_info_register(
link_address = args.get("link_address", ZERO_ADDRESS)
if link_address == _personal_info_contract.issuer.issuer_address:
block = await web3.eth.get_block(event["blockNumber"])
- timestamp = datetime.utcfromtimestamp(block["timestamp"])
+ timestamp = datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
decrypted_personal_info = (
await _personal_info_contract.get_info(
account_address=account_address, default_value=None
@@ -213,12 +217,13 @@ async def __sync_personal_info_register(
db_session=db_session,
account_address=account_address,
issuer_address=link_address,
+ event_type=PersonalInfoEventType.REGISTER,
personal_info=decrypted_personal_info,
timestamp=timestamp,
)
await db_session.commit()
except Exception:
- LOG.exception("An exception occurred during event synchronization")
+ raise
async def __sync_personal_info_modify(
self, db_session: AsyncSession, block_from, block_to
@@ -234,7 +239,9 @@ async def __sync_personal_info_modify(
link_address = args.get("link_address", ZERO_ADDRESS)
if link_address == _personal_info_contract.issuer.issuer_address:
block = await web3.eth.get_block(event["blockNumber"])
- timestamp = datetime.utcfromtimestamp(block["timestamp"])
+ timestamp = datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
decrypted_personal_info = (
await _personal_info_contract.get_info(
account_address=account_address, default_value=None
@@ -244,18 +251,20 @@ async def __sync_personal_info_modify(
db_session=db_session,
account_address=account_address,
issuer_address=link_address,
+ event_type=PersonalInfoEventType.MODIFY,
personal_info=decrypted_personal_info,
timestamp=timestamp,
)
await db_session.commit()
except Exception:
- LOG.exception("An exception occurred during event synchronization")
+ raise
@staticmethod
async def __sink_on_personal_info(
db_session: AsyncSession,
account_address: str,
issuer_address: str,
+ event_type: PersonalInfoEventType,
personal_info: dict,
timestamp: datetime,
):
@@ -292,6 +301,14 @@ async def __sink_on_personal_info(
f"Register: account_address={account_address}, issuer_address={issuer_address}"
)
+ _personal_info_history = IDXPersonalInfoHistory()
+ _personal_info_history.account_address = account_address
+ _personal_info_history.issuer_address = issuer_address
+ _personal_info_history.event_type = event_type
+ _personal_info_history.personal_info = _personal_info.personal_info
+ _personal_info_history.block_timestamp = timestamp
+ db_session.add(_personal_info_history)
+
async def main():
LOG.info("Service started successfully")
diff --git a/batch/indexer_position_bond.py b/batch/indexer_position_bond.py
index 114d3a57..719565b3 100644
--- a/batch/indexer_position_bond.py
+++ b/batch/indexer_position_bond.py
@@ -223,6 +223,7 @@ async def __sync_all(
await self.__sync_approve_transfer(db_session, block_from, block_to)
await self.__sync_exchange(db_session, block_from, block_to)
await self.__sync_escrow(db_session, block_from, block_to)
+ await self.__sync_dvp(db_session, block_from, block_to)
async def __sync_issuer(self, db_session: AsyncSession):
"""Synchronize issuer position"""
@@ -317,7 +318,7 @@ async def __sync_transfer(
args.get("from", ZERO_ADDRESS),
args.get("to", ZERO_ADDRESS),
]:
- if (await web3.eth.get_code(account)).hex() == "0x":
+ if (await web3.eth.get_code(account)).to_0x_hex() == "0x":
(
balance,
pending_transfer,
@@ -371,7 +372,7 @@ async def __sync_lock(
# Index Lock event
await self.__insert_lock_idx(
db_session=db_session,
- transaction_hash=event["transactionHash"].hex(),
+ transaction_hash=event["transactionHash"].to_0x_hex(),
msg_sender=msg_sender,
block_number=event["blockNumber"],
token_address=token.address,
@@ -479,7 +480,7 @@ async def __sync_unlock(
# Index Unlock event
await self.__insert_unlock_idx(
db_session=db_session,
- transaction_hash=event["transactionHash"].hex(),
+ transaction_hash=event["transactionHash"].to_0x_hex(),
msg_sender=msg_sender,
block_number=event["blockNumber"],
token_address=token.address,
@@ -979,6 +980,131 @@ async def __sync_escrow(
except Exception as e:
raise e
+ async def __sync_dvp(
+ self, db_session: AsyncSession, block_from: int, block_to: int
+ ):
+ """Sync Events from IbetSecurityTokenDVP
+
+ :param db_session: database session
+ :param block_from: From block
+ :param block_to: To block
+ :return: None
+ """
+ for exchange_address in self.exchange_address_list:
+ try:
+ dvp = AsyncContractUtils.get_contract(
+ "IbetSecurityTokenDVP", exchange_address
+ )
+
+ account_list_tmp = []
+
+ # DeliveryCreated event
+ _event_list = await AsyncContractUtils.get_event_logs(
+ contract=dvp,
+ event="DeliveryCreated",
+ block_from=block_from,
+ block_to=block_to,
+ )
+ for _event in _event_list:
+ account_list_tmp.append(
+ {
+ "token_address": _event["args"].get("token", ZERO_ADDRESS),
+ "account_address": _event["args"].get(
+ "seller", ZERO_ADDRESS
+ ), # only seller has changed
+ }
+ )
+
+ # DeliveryCanceled event
+ _event_list = await AsyncContractUtils.get_event_logs(
+ contract=dvp,
+ event="DeliveryCanceled",
+ block_from=block_from,
+ block_to=block_to,
+ )
+ for _event in _event_list:
+ account_list_tmp.append(
+ {
+ "token_address": _event["args"].get("token", ZERO_ADDRESS),
+ "account_address": _event["args"].get(
+ "seller", ZERO_ADDRESS
+ ), # only seller has changed
+ }
+ )
+
+ # DeliveryAborted event
+ _event_list = await AsyncContractUtils.get_event_logs(
+ contract=dvp,
+ event="DeliveryAborted",
+ block_from=block_from,
+ block_to=block_to,
+ )
+ for _event in _event_list:
+ account_list_tmp.append(
+ {
+ "token_address": _event["args"].get("token", ZERO_ADDRESS),
+ "account_address": _event["args"].get(
+ "seller", ZERO_ADDRESS
+ ), # only seller has changed
+ }
+ )
+
+ # HolderChanged event
+ _event_list = await AsyncContractUtils.get_event_logs(
+ contract=dvp,
+ event="HolderChanged",
+ block_from=block_from,
+ block_to=block_to,
+ )
+ for _event in _event_list:
+ account_list_tmp.append(
+ {
+ "token_address": _event["args"].get("token", ZERO_ADDRESS),
+ "account_address": _event["args"].get("from", ZERO_ADDRESS),
+ }
+ )
+ account_list_tmp.append(
+ {
+ "token_address": _event["args"].get("token", ZERO_ADDRESS),
+ "account_address": _event["args"].get("to", ZERO_ADDRESS),
+ }
+ )
+
+ # Make temporary list unique
+ account_list_tmp.sort(
+ key=lambda x: (x["token_address"], x["account_address"])
+ )
+ account_list = []
+ for k, g in groupby(
+ account_list_tmp,
+ lambda x: (x["token_address"], x["account_address"]),
+ ):
+ account_list.append(
+ {"token_address": k[0], "account_address": k[1]}
+ )
+
+ # Update position
+ for _account in account_list:
+ token_address = _account["token_address"]
+ account_address = _account["account_address"]
+ (
+ exchange_balance,
+ exchange_commitment,
+ ) = await self.__get_account_balance_exchange(
+ exchange_address=exchange_address,
+ token_address=token_address,
+ account_address=account_address,
+ )
+ await self.__sink_on_position(
+ db_session=db_session,
+ token_address=token_address,
+ account_address=account_address,
+ exchange_balance=exchange_balance,
+ exchange_commitment=exchange_commitment,
+ )
+ except Exception as e:
+ raise e
+
@staticmethod
async def __insert_lock_idx(
db_session: AsyncSession,
diff --git a/batch/indexer_position_share.py b/batch/indexer_position_share.py
index e17b80d0..818bf8aa 100644
--- a/batch/indexer_position_share.py
+++ b/batch/indexer_position_share.py
@@ -225,6 +225,7 @@ async def __sync_all(
await self.__sync_approve_transfer(db_session, block_from, block_to)
await self.__sync_exchange(db_session, block_from, block_to)
await self.__sync_escrow(db_session, block_from, block_to)
+ await self.__sync_dvp(db_session, block_from, block_to)
async def __sync_issuer(self, db_session: AsyncSession):
"""Synchronize issuer position"""
@@ -319,7 +320,7 @@ async def __sync_transfer(
args.get("from", ZERO_ADDRESS),
args.get("to", ZERO_ADDRESS),
]:
- if (await web3.eth.get_code(account)).hex() == "0x":
+ if (await web3.eth.get_code(account)).to_0x_hex() == "0x":
(
balance,
pending_transfer,
@@ -373,7 +374,7 @@ async def __sync_lock(
# Index Lock event
await self.__insert_lock_idx(
db_session=db_session,
- transaction_hash=event["transactionHash"].hex(),
+ transaction_hash=event["transactionHash"].to_0x_hex(),
msg_sender=msg_sender,
block_number=event["blockNumber"],
token_address=token.address,
@@ -481,7 +482,7 @@ async def __sync_unlock(
# Index Unlock event
await self.__insert_unlock_idx(
db_session=db_session,
- transaction_hash=event["transactionHash"].hex(),
+ transaction_hash=event["transactionHash"].to_0x_hex(),
msg_sender=msg_sender,
block_number=event["blockNumber"],
token_address=token.address,
@@ -981,6 +982,131 @@ async def __sync_escrow(
except Exception as e:
raise e
+ async def __sync_dvp(
+ self, db_session: AsyncSession, block_from: int, block_to: int
+ ):
+ """Sync Events from IbetSecurityTokenDVP
+
+ :param db_session: database session
+ :param block_from: From block
+ :param block_to: To block
+ :return: None
+ """
+ for exchange_address in self.exchange_address_list:
+ try:
+ delivery = AsyncContractUtils.get_contract(
+ "IbetSecurityTokenDVP", exchange_address
+ )
+
+ account_list_tmp = []
+
+ # DeliveryCreated event
+ _event_list = await AsyncContractUtils.get_event_logs(
+ contract=delivery,
+ event="DeliveryCreated",
+ block_from=block_from,
+ block_to=block_to,
+ )
+ for _event in _event_list:
+ account_list_tmp.append(
+ {
+ "token_address": _event["args"].get("token", ZERO_ADDRESS),
+ "account_address": _event["args"].get(
+ "seller", ZERO_ADDRESS
+ ), # only seller has changed
+ }
+ )
+
+ # DeliveryCanceled event
+ _event_list = await AsyncContractUtils.get_event_logs(
+ contract=delivery,
+ event="DeliveryCanceled",
+ block_from=block_from,
+ block_to=block_to,
+ )
+ for _event in _event_list:
+ account_list_tmp.append(
+ {
+ "token_address": _event["args"].get("token", ZERO_ADDRESS),
+ "account_address": _event["args"].get(
+ "seller", ZERO_ADDRESS
+ ), # only seller has changed
+ }
+ )
+
+ # DeliveryAborted event
+ _event_list = await AsyncContractUtils.get_event_logs(
+ contract=delivery,
+ event="DeliveryAborted",
+ block_from=block_from,
+ block_to=block_to,
+ )
+ for _event in _event_list:
+ account_list_tmp.append(
+ {
+ "token_address": _event["args"].get("token", ZERO_ADDRESS),
+ "account_address": _event["args"].get(
+ "seller", ZERO_ADDRESS
+ ), # only seller has changed
+ }
+ )
+
+ # HolderChanged event
+ _event_list = await AsyncContractUtils.get_event_logs(
+ contract=delivery,
+ event="HolderChanged",
+ block_from=block_from,
+ block_to=block_to,
+ )
+ for _event in _event_list:
+ account_list_tmp.append(
+ {
+ "token_address": _event["args"].get("token", ZERO_ADDRESS),
+ "account_address": _event["args"].get("from", ZERO_ADDRESS),
+ }
+ )
+ account_list_tmp.append(
+ {
+ "token_address": _event["args"].get("token", ZERO_ADDRESS),
+ "account_address": _event["args"].get("to", ZERO_ADDRESS),
+ }
+ )
+
+ # Make temporary list unique
+ account_list_tmp.sort(
+ key=lambda x: (x["token_address"], x["account_address"])
+ )
+ account_list = []
+ for k, g in groupby(
+ account_list_tmp,
+ lambda x: (x["token_address"], x["account_address"]),
+ ):
+ account_list.append(
+ {"token_address": k[0], "account_address": k[1]}
+ )
+
+ # Update position
+ for _account in account_list:
+ token_address = _account["token_address"]
+ account_address = _account["account_address"]
+ (
+ exchange_balance,
+ exchange_commitment,
+ ) = await self.__get_account_balance_exchange(
+ exchange_address=exchange_address,
+ token_address=token_address,
+ account_address=account_address,
+ )
+ await self.__sink_on_position(
+ db_session=db_session,
+ token_address=token_address,
+ account_address=account_address,
+ exchange_balance=exchange_balance,
+ exchange_commitment=exchange_commitment,
+ )
+ except Exception as e:
+ raise e
+
@staticmethod
async def __insert_lock_idx(
db_session: AsyncSession,
diff --git a/batch/indexer_token_holders.py b/batch/indexer_token_holders.py
index f64f22a1..a5e8f2ba 100644
--- a/batch/indexer_token_holders.py
+++ b/batch/indexer_token_holders.py
@@ -304,7 +304,7 @@ async def __process_transfer(self, block_from: int, block_to: int):
{
"event": _event["event"],
"args": dict(_event["args"]),
- "transaction_hash": _event["transactionHash"].hex(),
+ "transaction_hash": _event["transactionHash"].to_0x_hex(),
"block_number": _event["blockNumber"],
"log_index": _event["logIndex"],
}
@@ -322,7 +322,7 @@ async def __process_transfer(self, block_from: int, block_to: int):
{
"event": _event["event"],
"args": dict(_event["args"]),
- "transaction_hash": _event["transactionHash"].hex(),
+ "transaction_hash": _event["transactionHash"].to_0x_hex(),
"block_number": _event["blockNumber"],
"log_index": _event["logIndex"],
}
@@ -340,9 +340,9 @@ async def __process_transfer(self, block_from: int, block_to: int):
amount = int(args.get("value"))
# Skip sinking in case of deposit to exchange or withdrawal from exchange
- if (await web3.eth.get_code(from_account)).hex() != "0x" or (
+ if (await web3.eth.get_code(from_account)).to_0x_hex() != "0x" or (
await web3.eth.get_code(to_account)
- ).hex() != "0x":
+ ).to_0x_hex() != "0x":
continue
if amount is not None and amount <= sys.maxsize:
diff --git a/batch/indexer_transfer.py b/batch/indexer_transfer.py
index d58f33bf..08313524 100644
--- a/batch/indexer_transfer.py
+++ b/batch/indexer_transfer.py
@@ -20,7 +20,7 @@
import asyncio
import json
import sys
-from datetime import datetime
+from datetime import UTC, datetime
from typing import Sequence
import uvloop
@@ -201,10 +201,11 @@ async def __sync_transfer(
)
for event in events:
args = event["args"]
- transaction_hash = event["transactionHash"].hex()
- block_timestamp = datetime.utcfromtimestamp(
- (await web3.eth.get_block(event["blockNumber"]))["timestamp"]
- )
+ transaction_hash = event["transactionHash"].to_0x_hex()
+ block_timestamp = datetime.fromtimestamp(
+ (await web3.eth.get_block(event["blockNumber"]))["timestamp"],
+ UTC,
+ ).replace(tzinfo=None)
if args["value"] > sys.maxsize:
pass
else:
@@ -242,10 +243,11 @@ async def __sync_unlock(
)
for event in events:
args = event["args"]
- transaction_hash = event["transactionHash"].hex()
- block_timestamp = datetime.utcfromtimestamp(
- (await web3.eth.get_block(event["blockNumber"]))["timestamp"]
- )
+ transaction_hash = event["transactionHash"].to_0x_hex()
+ block_timestamp = datetime.fromtimestamp(
+ (await web3.eth.get_block(event["blockNumber"]))["timestamp"],
+ UTC,
+ ).replace(tzinfo=None)
if args["value"] > sys.maxsize:
pass
else:
diff --git a/batch/indexer_transfer_approval.py b/batch/indexer_transfer_approval.py
index 2ef6ab62..d9098643 100644
--- a/batch/indexer_transfer_approval.py
+++ b/batch/indexer_transfer_approval.py
@@ -20,7 +20,7 @@
import asyncio
import sys
import uuid
-from datetime import datetime, timezone
+from datetime import UTC, datetime
from typing import Optional, Sequence
import uvloop
@@ -284,7 +284,7 @@ async def __sync_token_apply_for_transfer(
notice_code=0,
)
except Exception:
- LOG.exception("An exception occurred during event synchronization")
+ raise
async def __sync_token_cancel_transfer(
self, db_session: AsyncSession, block_from, block_to
@@ -326,7 +326,7 @@ async def __sync_token_cancel_transfer(
notice_code=1,
)
except Exception:
- LOG.exception("An exception occurred during event synchronization")
+ raise
async def __sync_token_approve_transfer(
self, db_session: AsyncSession, block_from, block_to
@@ -369,7 +369,7 @@ async def __sync_token_approve_transfer(
notice_code=2,
)
except Exception:
- LOG.exception("An exception occurred during event synchronization")
+ raise
async def __sync_exchange_apply_for_transfer(
self, db_session: AsyncSession, block_from, block_to
@@ -417,7 +417,7 @@ async def __sync_exchange_apply_for_transfer(
notice_code=0,
)
except Exception:
- LOG.exception("An exception occurred during event synchronization")
+ raise
async def __sync_exchange_cancel_transfer(
self, db_session: AsyncSession, block_from, block_to
@@ -459,7 +459,7 @@ async def __sync_exchange_cancel_transfer(
notice_code=1,
)
except Exception:
- LOG.exception("An exception occurred during event synchronization")
+ raise
async def __sync_exchange_escrow_finished(
self, db_session: AsyncSession, block_from: int, block_to: int
@@ -500,7 +500,7 @@ async def __sync_exchange_escrow_finished(
notice_code=3,
)
except Exception:
- LOG.exception("An exception occurred during event synchronization")
+ raise
async def __sync_exchange_approve_transfer(
self, db_session: AsyncSession, block_from: int, block_to: int
@@ -541,7 +541,7 @@ async def __sync_exchange_approve_transfer(
notice_code=2,
)
except Exception:
- LOG.exception("An exception occurred during event synchronization")
+ raise
async def __register_notification(
self,
@@ -665,17 +665,17 @@ async def __sink_on_transfer_approval(
transfer_approval.amount = amount
try:
transfer_approval.application_datetime = datetime.fromtimestamp(
- float(optional_data_applicant), tz=timezone.utc
+ float(optional_data_applicant), tz=UTC
)
except ValueError:
transfer_approval.application_datetime = None
transfer_approval.application_blocktimestamp = datetime.fromtimestamp(
- block_timestamp, tz=timezone.utc
+ block_timestamp, tz=UTC
)
elif event_type == "Cancel":
if transfer_approval is not None:
transfer_approval.cancellation_blocktimestamp = datetime.fromtimestamp(
- block_timestamp, tz=timezone.utc
+ block_timestamp, tz=UTC
)
transfer_approval.cancelled = True
elif event_type == "EscrowFinish":
@@ -685,12 +685,12 @@ async def __sink_on_transfer_approval(
if transfer_approval is not None:
try:
transfer_approval.approval_datetime = datetime.fromtimestamp(
- float(optional_data_approver), tz=timezone.utc
+ float(optional_data_approver), tz=UTC
)
except ValueError:
transfer_approval.approval_datetime = None
transfer_approval.approval_blocktimestamp = datetime.fromtimestamp(
- block_timestamp, tz=timezone.utc
+ block_timestamp, tz=UTC
)
transfer_approval.transfer_approved = True
await db_session.merge(transfer_approval)
diff --git a/batch/processor_create_utxo.py b/batch/processor_create_utxo.py
index c6d14bac..eaa4cd1d 100644
--- a/batch/processor_create_utxo.py
+++ b/batch/processor_create_utxo.py
@@ -20,7 +20,7 @@
import asyncio
import sys
import time
-from datetime import datetime
+from datetime import UTC, datetime
from typing import Sequence
import uvloop
@@ -226,7 +226,7 @@ async def __process_transfer(
{
"event": _event["event"],
"args": dict(_event["args"]),
- "transaction_hash": _event["transactionHash"].hex(),
+ "transaction_hash": _event["transactionHash"].to_0x_hex(),
"block_number": _event["blockNumber"],
"log_index": _event["logIndex"],
}
@@ -244,7 +244,7 @@ async def __process_transfer(
{
"event": _event["event"],
"args": dict(_event["args"]),
- "transaction_hash": _event["transactionHash"].hex(),
+ "transaction_hash": _event["transactionHash"].to_0x_hex(),
"block_number": _event["blockNumber"],
"log_index": _event["logIndex"],
}
@@ -266,7 +266,7 @@ async def __process_transfer(
{
"event": _event["event"],
"args": dict(_event["args"]),
- "transaction_hash": _event["transactionHash"].hex(),
+ "transaction_hash": _event["transactionHash"].to_0x_hex(),
"block_number": _event["blockNumber"],
"log_index": _event["logIndex"],
}
@@ -291,15 +291,17 @@ async def __process_transfer(
amount = int(args.get("value"))
# Skip sinking in case of deposit to exchange or withdrawal from exchange
- if (await web3.eth.get_code(from_account)).hex() != "0x" or (
+ if (await web3.eth.get_code(from_account)).to_0x_hex() != "0x" or (
await web3.eth.get_code(to_account)
- ).hex() != "0x":
+ ).to_0x_hex() != "0x":
continue
transaction_hash = event["transaction_hash"]
block_number = event["block_number"]
- block_timestamp = datetime.utcfromtimestamp(
- (await web3.eth.get_block(block_number))["timestamp"]
+ block_timestamp = datetime.fromtimestamp(
+ (await web3.eth.get_block(block_number))["timestamp"], UTC
+ ).replace(
+ tzinfo=None
) # UTC
if amount is not None and amount <= sys.maxsize:
@@ -368,10 +370,12 @@ async def __process_issue(
account = args.get("targetAddress", ZERO_ADDRESS)
amount = args.get("amount")
- transaction_hash = event["transactionHash"].hex()
+ transaction_hash = event["transactionHash"].to_0x_hex()
block_number = event["blockNumber"]
- block_timestamp = datetime.utcfromtimestamp(
- (await web3.eth.get_block(block_number))["timestamp"]
+ block_timestamp = datetime.fromtimestamp(
+ (await web3.eth.get_block(block_number))["timestamp"], UTC
+ ).replace(
+ tzinfo=None
) # UTC
if amount is not None and amount <= sys.maxsize:
@@ -428,10 +432,12 @@ async def __process_redeem(
account = args.get("targetAddress", ZERO_ADDRESS)
amount = args.get("amount")
- transaction_hash = event["transactionHash"].hex()
+ transaction_hash = event["transactionHash"].to_0x_hex()
block_number = event["blockNumber"]
- block_timestamp = datetime.utcfromtimestamp(
- (await web3.eth.get_block(block_number))["timestamp"]
+ block_timestamp = datetime.fromtimestamp(
+ (await web3.eth.get_block(block_number))["timestamp"], UTC
+ ).replace(
+ tzinfo=None
) # UTC
if amount is not None and amount <= sys.maxsize:
diff --git a/batch/processor_monitor_block_sync.py b/batch/processor_monitor_block_sync.py
index dfda20ac..a173c591 100644
--- a/batch/processor_monitor_block_sync.py
+++ b/batch/processor_monitor_block_sync.py
@@ -25,8 +25,8 @@
from sqlalchemy import delete, select
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.ext.asyncio import AsyncSession
-from web3 import AsyncWeb3, Web3
-from web3.middleware import async_geth_poa_middleware
+from web3 import AsyncHTTPProvider, AsyncWeb3, Web3
+from web3.middleware import ExtraDataToPOAMiddleware
from app.database import BatchAsyncSessionLocal
from app.exceptions import ServiceUnavailableError
@@ -121,8 +121,8 @@ async def __set_node_info(
):
self.node_info[endpoint_uri] = {"priority": priority}
- web3 = AsyncWeb3(Web3.AsyncHTTPProvider(endpoint_uri))
- web3.middleware_onion.inject(async_geth_poa_middleware, layer=0)
+ web3 = AsyncWeb3(AsyncHTTPProvider(endpoint_uri))
+ web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
self.node_info[endpoint_uri]["web3"] = web3
# Get block number
diff --git a/batch/processor_rotate_e2e_messaging_rsa_key.py b/batch/processor_rotate_e2e_messaging_rsa_key.py
index 653b794f..d30a2fd3 100644
--- a/batch/processor_rotate_e2e_messaging_rsa_key.py
+++ b/batch/processor_rotate_e2e_messaging_rsa_key.py
@@ -20,7 +20,7 @@
import asyncio
import sys
import time
-from datetime import datetime
+from datetime import UTC, datetime
from typing import Sequence
import uvloop
@@ -176,9 +176,9 @@ async def __auto_generate_rsa_key(
_account_rsa_key.rsa_private_key = rsa_private_key
_account_rsa_key.rsa_public_key = rsa_public_key
_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(pass_phrase)
- _account_rsa_key.block_timestamp = datetime.utcfromtimestamp(
- block["timestamp"]
- )
+ _account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
db_session.add(_account_rsa_key)
@staticmethod
diff --git a/batch/processor_scheduled_events.py b/batch/processor_scheduled_events.py
index c2b1b036..5e5f9070 100644
--- a/batch/processor_scheduled_events.py
+++ b/batch/processor_scheduled_events.py
@@ -21,7 +21,7 @@
import sys
import time
import uuid
-from datetime import datetime
+from datetime import UTC, datetime, timezone
from typing import List, Optional, Sequence, Set
import uvloop
@@ -78,7 +78,7 @@ def __init__(self, worker_num: int):
async def process(self):
db_session: AsyncSession = BatchAsyncSessionLocal()
try:
- process_start_time = datetime.utcnow()
+ process_start_time = datetime.now(UTC).replace(tzinfo=None)
while True:
events_list = await self.__get_events_of_one_issuer(
db_session=db_session, filter_time=process_start_time
diff --git a/batch/processor_update_token.py b/batch/processor_update_token.py
index 881e7d8c..19518d2a 100644
--- a/batch/processor_update_token.py
+++ b/batch/processor_update_token.py
@@ -20,7 +20,7 @@
import asyncio
import sys
import uuid
-from datetime import datetime
+from datetime import UTC, datetime
from typing import Sequence
import uvloop
@@ -211,9 +211,9 @@ async def process(self):
_utxo.token_address = _update_token.token_address
_utxo.amount = _update_token.arguments.get("total_supply")
_utxo.block_number = block["number"]
- _utxo.block_timestamp = datetime.utcfromtimestamp(
- block["timestamp"]
- )
+ _utxo.block_timestamp = datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
db_session.add(_utxo)
await self.__sink_on_finish_update_process(
@@ -272,53 +272,57 @@ def __create_update_data(trigger, token_type, arguments: dict):
if trigger == "Issue":
# NOTE: Items set at the time of issue do not need to be updated.
if token_type == TokenType.IBET_SHARE.value:
- update_data = {
- "tradable_exchange_contract_address": arguments.get(
+ return IbetShareUpdateParams(
+ tradable_exchange_contract_address=arguments.get(
"tradable_exchange_contract_address"
),
- "personal_info_contract_address": arguments.get(
+ personal_info_contract_address=arguments.get(
"personal_info_contract_address"
),
- "transferable": arguments.get("transferable"),
- "status": arguments.get("status"),
- "is_offering": arguments.get("is_offering"),
- "contact_information": arguments.get("contact_information"),
- "privacy_policy": arguments.get("privacy_policy"),
- "transfer_approval_required": arguments.get(
+ require_personal_info_registered=arguments.get(
+ "require_personal_info_registered"
+ ),
+ transferable=arguments.get("transferable"),
+ status=arguments.get("status"),
+ is_offering=arguments.get("is_offering"),
+ contact_information=arguments.get("contact_information"),
+ privacy_policy=arguments.get("privacy_policy"),
+ transfer_approval_required=arguments.get(
"transfer_approval_required"
),
- "is_canceled": arguments.get("is_canceled"),
- }
- return IbetShareUpdateParams(**update_data)
+ is_canceled=arguments.get("is_canceled"),
+ )
elif token_type == TokenType.IBET_STRAIGHT_BOND.value:
- update_data = {
- "face_value_currency": arguments.get("face_value_currency"),
- "redemption_value_currency": arguments.get(
+ return IbetStraightBondUpdateParams(
+ face_value_currency=arguments.get("face_value_currency"),
+ redemption_value_currency=arguments.get(
"redemption_value_currency"
),
- "interest_rate": arguments.get("interest_rate"),
- "interest_payment_date": arguments.get("interest_payment_date"),
- "interest_payment_currency": arguments.get(
+ interest_rate=arguments.get("interest_rate"),
+ interest_payment_date=arguments.get("interest_payment_date"),
+ interest_payment_currency=arguments.get(
"interest_payment_currency"
),
- "base_fx_rate": arguments.get("base_fx_rate"),
- "transferable": arguments.get("transferable"),
- "status": arguments.get("status"),
- "is_offering": arguments.get("is_offering"),
- "is_redeemed": arguments.get("is_redeemed"),
- "tradable_exchange_contract_address": arguments.get(
+ base_fx_rate=arguments.get("base_fx_rate"),
+ transferable=arguments.get("transferable"),
+ status=arguments.get("status"),
+ is_offering=arguments.get("is_offering"),
+ is_redeemed=arguments.get("is_redeemed"),
+ tradable_exchange_contract_address=arguments.get(
"tradable_exchange_contract_address"
),
- "personal_info_contract_address": arguments.get(
+ personal_info_contract_address=arguments.get(
"personal_info_contract_address"
),
- "contact_information": arguments.get("contact_information"),
- "privacy_policy": arguments.get("privacy_policy"),
- "transfer_approval_required": arguments.get(
+ require_personal_info_registered=arguments.get(
+ "require_personal_info_registered"
+ ),
+ contact_information=arguments.get("contact_information"),
+ privacy_policy=arguments.get("privacy_policy"),
+ transfer_approval_required=arguments.get(
"transfer_approval_required"
),
- }
- return IbetStraightBondUpdateParams(**update_data)
+ )
return
@staticmethod
diff --git a/bin/healthcheck_indexer.sh b/bin/healthcheck_indexer.sh
index 6c193dbc..def0c669 100755
--- a/bin/healthcheck_indexer.sh
+++ b/bin/healthcheck_indexer.sh
@@ -25,6 +25,7 @@ PROC_LIST="${PROC_LIST} batch/indexer_transfer.py"
PROC_LIST="${PROC_LIST} batch/indexer_transfer_approval.py"
PROC_LIST="${PROC_LIST} batch/indexer_issue_redeem.py"
PROC_LIST="${PROC_LIST} batch/indexer_token_cache.py"
+PROC_LIST="${PROC_LIST} batch/indexer_delivery.py"
if [ -n "${E2E_MESSAGING_CONTRACT_ADDRESS}" ]; then
PROC_LIST="${PROC_LIST} batch/indexer_e2e_messaging.py"
diff --git a/bin/run_indexer.sh b/bin/run_indexer.sh
index 4ce334c5..4a3aa8a5 100755
--- a/bin/run_indexer.sh
+++ b/bin/run_indexer.sh
@@ -29,6 +29,7 @@ python batch/indexer_transfer.py &
python batch/indexer_transfer_approval.py &
python batch/indexer_issue_redeem.py &
python batch/indexer_token_cache.py &
+python batch/indexer_delivery.py &
if [ -n "${E2E_MESSAGING_CONTRACT_ADDRESS}" ]; then
python batch/indexer_e2e_messaging.py &
diff --git a/cmd/explorer/poetry.lock b/cmd/explorer/poetry.lock
index 625691d3..91b597d5 100644
--- a/cmd/explorer/poetry.lock
+++ b/cmd/explorer/poetry.lock
@@ -3,5 +3,5 @@ package = []
[metadata]
lock-version = "2.0"
-python-versions = "3.11.2"
+python-versions = "3.12.2"
content-hash = "5238f2940f85ee545d00dfdc196d3dc793fbad517b6ee1172c9644982f7fe101"
diff --git a/cmd/explorer/pyproject.toml b/cmd/explorer/pyproject.toml
index cdc2b5fb..52853d44 100644
--- a/cmd/explorer/pyproject.toml
+++ b/cmd/explorer/pyproject.toml
@@ -5,17 +5,17 @@ description = "ibet-Prime Terminal UI for Block Chain Explorer"
authors = ["BOOSTRY Co., Ltd. "]
readme = "README.md"
packages = [
- { include = "src" },
+ { include = "../explorer" },
]
[tool.poetry.dependencies]
-python = "3.11.2"
+python = "3.12.2"
[tool.poetry.scripts]
-ibet-explorer = "src.main:app"
+ibet-explorer = "explorer.src.main:app"
[tool.mypy]
-python_version = "3.11"
+python_version = "3.12"
no_strict_optional = true
ignore_missing_imports = true
check_untyped_defs = true
diff --git a/cmd/explorer/src/connector/__init__.py b/cmd/explorer/src/connector/__init__.py
index eedcba83..4e197735 100644
--- a/cmd/explorer/src/connector/__init__.py
+++ b/cmd/explorer/src/connector/__init__.py
@@ -21,6 +21,7 @@
from typing import Any
from aiohttp import ClientSession
+from cache import AsyncTTL
from app.model.schema import (
BlockDataDetail,
@@ -31,7 +32,6 @@
TxDataDetail,
TxDataListResponse,
)
-from cache import AsyncTTL
class ApiNotEnabledException(Exception):
diff --git a/cmd/settlement/Makefile b/cmd/settlement/Makefile
new file mode 100644
index 00000000..fe3aafb4
--- /dev/null
+++ b/cmd/settlement/Makefile
@@ -0,0 +1,18 @@
+.PHONY: isort black test run
+
+format: isort black
+
+isort:
+ isort src/.
+
+black:
+ poetry run black src
+
+test:
+ pytest .
+
+console:
+ textual console
+
+run:
+ poetry run python src/main.py
\ No newline at end of file
diff --git a/cmd/settlement/README.md b/cmd/settlement/README.md
new file mode 100644
index 00000000..3fc61cde
--- /dev/null
+++ b/cmd/settlement/README.md
@@ -0,0 +1,94 @@
+# ibet settlement CLI
+
+## Run
+
+### with container
+
+```bash
+> docker exec -it -e "TERM=xterm-256color" ibet-prime-app bash --login
+> apl@2e5a80e06fcb:/$ settlement-cli --help
+
+ Usage: settlement-cli [OPTIONS] COMMAND [ARGS]...
+
+╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
+│ --install-completion Install completion for the current shell. │
+│ --show-completion Show completion for the current shell, to copy it or customize the installation. │
+│ --help Show this message and exit. │
+╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
+╭─ Commands ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
+│ abort │
+│ create_agent │
+│ finish │
+│ list │
+╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
+```
+
+## Commands
+
+### List
+
+```bash
+ Usage: settlement-cli list [OPTIONS] EXCHANGE_ADDRESS AGENT_ADDRESS [STATUS]:[DELIVER
+ Y_CREATED|DELIVERY_CANCELED|DELIVERY_CONFIRMED|DELIVERY_FI
+ NISHED|DELIVERY_ABORTED] [API_URL]
+
+╭─ Arguments ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
+│ * exchange_address TEXT [default: None] [required] │
+│ * agent_address TEXT [default: None] [required] │
+│ status [STATUS]:[DELIVERY_CREATED|DELIVERY_CANCELED|DELIVERY_CONFIRMED|DELIVERY_FINISHED|DELIVERY_ABORTED] [default: delivery_confirmed] │
+│ api_url [API_URL] [env var: API_URL] [default: http://localhost:5000] │
+╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
+╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
+│ --help Show this message and exit. │
+╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
+```
+
+### Finish
+
+```bash
+ Usage: settlement-cli finish [OPTIONS] EXCHANGE_ADDRESS AGENT_ADDRESS DELIVERY_ID
+ [EOA_PASSWORD] [API_URL]
+
+╭─ Arguments ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
+│ * exchange_address TEXT [default: None] [required] │
+│ * agent_address TEXT [default: None] [required] │
+│ * delivery_id INTEGER [default: None] [required] │
+│ eoa_password [EOA_PASSWORD] [env var: EOA_PASSWORD] [default: None] │
+│ api_url [API_URL] [env var: API_URL] [default: http://localhost:5000] │
+╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
+╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
+│ --help Show this message and exit. │
+╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
+```
+
+### Abort
+
+```bash
+ Usage: settlement-cli abort [OPTIONS] EXCHANGE_ADDRESS AGENT_ADDRESS DELIVERY_ID
+ [EOA_PASSWORD] [API_URL]
+
+╭─ Arguments ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
+│ * exchange_address TEXT [default: None] [required] │
+│ * agent_address TEXT [default: None] [required] │
+│ * delivery_id INTEGER [default: None] [required] │
+│ eoa_password [EOA_PASSWORD] [env var: EOA_PASSWORD] [default: None] │
+│ api_url [API_URL] [env var: API_URL] [default: http://localhost:5000] │
+╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
+╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
+│ --help Show this message and exit. │
+╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
+```
+
+### Create DVP Agent
+
+```bash
+ Usage: settlement-cli create_agent [OPTIONS] EOA_PASSWORD [API_URL]
+
+╭─ Arguments ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
+│ * eoa_password TEXT [env var: EOA_PASSWORD] [default: None] [required] │
+│ api_url [API_URL] [env var: API_URL] [default: http://localhost:5000] │
+╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
+╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
+│ --help Show this message and exit. │
+╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
+```
\ No newline at end of file
diff --git a/cmd/settlement/pyproject.toml b/cmd/settlement/pyproject.toml
new file mode 100644
index 00000000..082eaa67
--- /dev/null
+++ b/cmd/settlement/pyproject.toml
@@ -0,0 +1,25 @@
+[tool.poetry]
+name = "ibet-prime-settlement"
+version = "0.1.0"
+description = "ibet-Prime Settlement CLI"
+authors = ["BOOSTRY Co., Ltd. "]
+readme = "README.md"
+packages = [
+ { include = "../settlement" },
+]
+
+[tool.poetry.dependencies]
+python = "3.12.2"
+
+[tool.poetry.scripts]
+settlement-cli = "settlement.src.main:app"
+
+[tool.mypy]
+python_version = "3.12"
+no_strict_optional = true
+ignore_missing_imports = true
+check_untyped_defs = true
+
+[build-system]
+requires = ["poetry-core>=1.0.0"]
+build-backend = "poetry.core.masonry.api"
\ No newline at end of file
diff --git a/cmd/settlement/src/__init__.py b/cmd/settlement/src/__init__.py
new file mode 100644
index 00000000..5ebbd941
--- /dev/null
+++ b/cmd/settlement/src/__init__.py
@@ -0,0 +1,18 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
diff --git a/cmd/settlement/src/main.py b/cmd/settlement/src/main.py
new file mode 100644
index 00000000..9430beff
--- /dev/null
+++ b/cmd/settlement/src/main.py
@@ -0,0 +1,237 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+import base64
+import json
+import logging
+import sys
+from typing import Annotated
+
+import click
+import httpx
+import typer
+from Crypto.Cipher import PKCS1_OAEP
+from Crypto.PublicKey import RSA
+from rich import print
+from rich.console import Console
+from rich.table import Table
+
+from app.model.db import DeliveryStatus
+from app.model.schema import (
+ AbortDVPDeliveryRequest,
+ CreateDVPAgentAccountRequest,
+ FinishDVPDeliveryRequest,
+)
+
+logging.getLogger("httpx").setLevel(logging.WARNING)
+logging.getLogger("httpcore").setLevel(logging.WARNING)
+
+
+app = typer.Typer(pretty_exceptions_show_locals=False)
+
+
+@app.command(name="list")
+def list_deliveries(
+ exchange_address: str,
+ agent_address: str,
+ status: Annotated[
+ str,
+ typer.Argument(
+ click_type=click.Choice(
+ [DeliveryStatus(d).name for d in DeliveryStatus], case_sensitive=False
+ )
+ ),
+ ] = "delivery_confirmed",
+ api_url: Annotated[
+ str, typer.Argument(..., envvar="API_URL")
+ ] = "http://localhost:5000",
+):
+ resp = httpx.get(
+ url=f"{api_url}/settlement/dvp/{exchange_address}/deliveries",
+ params={
+ "agent_address": agent_address,
+ "status": DeliveryStatus[status.upper()].value,
+ },
+ )
+
+ if resp.status_code != 200:
+ typer.echo(typer.style("Failed to get deliveries", fg="red"), err=True)
+ print(resp.json())
+ sys.exit(1)
+
+ console = Console()
+
+ delivery_table = Table()
+ delivery_table.add_column("Delivery ID")
+ delivery_table.add_column("Token Address")
+ delivery_table.add_column("Buyer")
+ delivery_table.add_column("Seller")
+ delivery_table.add_column("Amount")
+ delivery_table.add_column("Agent")
+ delivery_table.add_column("Data")
+ delivery_table.add_column("Status")
+
+ for idx_delivery in resp.json()["deliveries"]:
+ match idx_delivery["status"]:
+ case DeliveryStatus.DELIVERY_CREATED:
+ status = "Created"
+ case DeliveryStatus.DELIVERY_CANCELED:
+ status = "Canceled"
+ case DeliveryStatus.DELIVERY_CONFIRMED:
+ status = "Confirmed"
+ case DeliveryStatus.DELIVERY_FINISHED:
+ status = "Finished"
+ case DeliveryStatus.DELIVERY_ABORTED:
+ status = "Aborted"
+ case _:
+ status = None
+
+ delivery_table.add_row(
+ str(idx_delivery["delivery_id"]),
+ idx_delivery["token_address"],
+ idx_delivery["buyer_address"],
+ idx_delivery["seller_address"],
+ str(idx_delivery["amount"]),
+ idx_delivery["agent_address"],
+ idx_delivery["data"],
+ status,
+ )
+
+ console.print(delivery_table)
+
+
+@app.command(name="finish")
+def finish(
+ exchange_address: str,
+ agent_address: str,
+ delivery_id: int,
+ eoa_password: Annotated[str, typer.Argument(..., envvar="EOA_PASSWORD")] = None,
+ api_url: Annotated[
+ str, typer.Argument(..., envvar="API_URL")
+ ] = "http://localhost:5000",
+):
+ resp = httpx.get(url=f"{api_url}/e2ee")
+
+ if resp.status_code != 200:
+ print("Failed to get e2ee pubkey")
+ print(resp.json())
+ sys.exit(1)
+
+ if resp.json()["public_key"] is not None:
+ rsa_publickey = RSA.importKey(resp.json()["public_key"])
+ cipher = PKCS1_OAEP.new(rsa_publickey)
+ eoa_password = base64.encodebytes(cipher.encrypt(eoa_password.encode("utf-8")))
+
+ finish_params = FinishDVPDeliveryRequest(
+ operation_type="Finish",
+ account_address=agent_address,
+ eoa_password=eoa_password,
+ )
+
+ resp = httpx.post(
+ url=f"{api_url}/settlement/dvp/{exchange_address}/delivery/{delivery_id}",
+ json=json.loads(finish_params.model_dump_json()),
+ )
+
+ if resp.status_code != 200:
+ typer.echo(typer.style("Failed to finish the delivery", fg="red"), err=True)
+ print(resp.json())
+ sys.exit(1)
+
+ typer.echo(typer.style("Successfully finished the delivery", fg="blue"))
+ print(f"delivery_id: {delivery_id}")
+
+
+@app.command(name="abort")
+def abort(
+ exchange_address: str,
+ agent_address: str,
+ delivery_id: int,
+ eoa_password: Annotated[str, typer.Argument(..., envvar="EOA_PASSWORD")] = None,
+ api_url: Annotated[
+ str, typer.Argument(..., envvar="API_URL")
+ ] = "http://localhost:5000",
+):
+ resp = httpx.get(url=f"{api_url}/e2ee")
+
+ if resp.status_code != 200:
+ print("Failed to get e2ee pubkey")
+ print(resp.json())
+ sys.exit(1)
+
+ if resp.json()["public_key"] is not None:
+ rsa_publickey = RSA.importKey(resp.json()["public_key"])
+ cipher = PKCS1_OAEP.new(rsa_publickey)
+ eoa_password = base64.encodebytes(cipher.encrypt(eoa_password.encode("utf-8")))
+
+ abort_params = AbortDVPDeliveryRequest(
+ operation_type="Abort", account_address=agent_address, eoa_password=eoa_password
+ )
+
+ resp = httpx.post(
+ url=f"{api_url}/settlement/dvp/{exchange_address}/delivery/{delivery_id}",
+ json=json.loads(abort_params.model_dump_json()),
+ )
+
+ if resp.status_code != 200:
+ typer.echo(typer.style("Failed to abort the delivery", fg="red"), err=True)
+ print(resp.json())
+ sys.exit(1)
+
+ typer.echo(typer.style("Successfully aborted the delivery", fg="blue"))
+ print(f"delivery_id: {delivery_id}")
+
+
+@app.command(name="create_agent")
+def create_agent(
+ eoa_password: Annotated[str, typer.Argument(..., envvar="EOA_PASSWORD")],
+ api_url: Annotated[
+ str, typer.Argument(..., envvar="API_URL")
+ ] = "http://localhost:5000",
+):
+ resp = httpx.get(url=f"{api_url}/e2ee")
+
+ if resp.status_code != 200:
+ print("Failed to get e2ee pubkey")
+ print(resp.json())
+ sys.exit(1)
+
+ if resp.json()["public_key"] is not None:
+ rsa_publickey = RSA.importKey(resp.json()["public_key"])
+ cipher = PKCS1_OAEP.new(rsa_publickey)
+ eoa_password = base64.encodebytes(cipher.encrypt(eoa_password.encode("utf-8")))
+
+ create_agent_param = CreateDVPAgentAccountRequest(eoa_password=eoa_password)
+
+ resp = httpx.post(
+ url=f"{api_url}/settlement/dvp/agent/accounts",
+ json=json.loads(create_agent_param.model_dump_json()),
+ )
+
+ if resp.status_code != 200:
+ typer.echo(typer.style("Failed to create agent account", fg="red"), err=True)
+ print(resp.json())
+ sys.exit(1)
+
+ typer.echo(typer.style("Successfully created agent account", fg="blue"))
+ print(f"account_address: {resp.json()['account_address']}")
+
+
+if __name__ == "__main__":
+ app()
diff --git a/contracts/DVPStorage.json b/contracts/DVPStorage.json
new file mode 100644
index 00000000..62e7d3ed
--- /dev/null
+++ b/contracts/DVPStorage.json
@@ -0,0 +1,335 @@
+{
+ "abi": [
+ {
+ "inputs": [],
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "previousOwner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "newOwner",
+ "type": "address"
+ }
+ ],
+ "name": "OwnershipTransferred",
+ "type": "event"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "commitments",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_account",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "_token",
+ "type": "address"
+ }
+ ],
+ "name": "getBalance",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_account",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "_token",
+ "type": "address"
+ }
+ ],
+ "name": "getCommitment",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "_deliveryId",
+ "type": "uint256"
+ }
+ ],
+ "name": "getDelivery",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "seller",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "buyer",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "agent",
+ "type": "address"
+ },
+ {
+ "internalType": "bool",
+ "name": "confirmed",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "valid",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getLatestDeliveryId",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "latestVersion",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "owner",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_account",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "_token",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "setBalance",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_account",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "_token",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "setCommitment",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "_deliveryId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "_token",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "_seller",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "_buyer",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "_agent",
+ "type": "address"
+ },
+ {
+ "internalType": "bool",
+ "name": "_confirmed",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "_valid",
+ "type": "bool"
+ }
+ ],
+ "name": "setDelivery",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "_latestDeliveryId",
+ "type": "uint256"
+ }
+ ],
+ "name": "setLatestDeliveryId",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "newOwner",
+ "type": "address"
+ }
+ ],
+ "name": "transferOwnership",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_newVersion",
+ "type": "address"
+ }
+ ],
+ "name": "upgradeVersion",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+ ],
+ "bytecode": "6080604052600060055534801561001557600080fd5b50600080546001600160a01b0319163317905561086b806100376000396000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c8063d04c23af1161008c578063de8211a911610066578063de8211a914610215578063ecf89597146102c3578063f2fde38b146102d6578063fd44b92e146102e957600080fd5b8063d04c23af146101b4578063d28eb963146101c7578063d4fac45d146101dc57600080fd5b8063097d9012146100d45780638da5cb5b1461012057806399933b331461014b578063adb6f63f14610153578063b5c9cbbe1461017e578063c07f47d4146101a1575b600080fd5b61010d6100e23660046106a3565b6001600160a01b03918216600090815260036020908152604080832093909416825291909152205490565b6040519081526020015b60405180910390f35b600054610133906001600160a01b031681565b6040516001600160a01b039091168152602001610117565b60055461010d565b61010d6101613660046106a3565b600360209081526000928352604080842090915290825290205481565b61019161018c3660046106d6565b6102fc565b6040519015158152602001610117565b600154610133906001600160a01b031681565b6101916101c23660046106d6565b610381565b6101da6101d5366004610712565b6103fd565b005b61010d6101ea3660046106a3565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b610278610223366004610734565b6000908152600460208190526040909120805460018201546002830154600384015493909401546001600160a01b0392831695918316948316939281169160ff600160a01b8304811692600160a81b90041690565b604080516001600160a01b0398891681529688166020880152948716948601949094526060850192909252909316608083015291151560a082015290151560c082015260e001610117565b6101da6102d136600461075d565b610469565b6101da6102e4366004610712565b61054e565b6101da6102f7366004610734565b610638565b60015460408051808201909152600681526532353030303160d01b60208201526000916001600160a01b031633146103505760405162461bcd60e51b815260040161034791906107e6565b60405180910390fd5b50506001600160a01b0392831660009081526002602090815260408083209490951682529290925291902055600190565b60015460408051808201909152600681526532353030303160d01b60208201526000916001600160a01b031633146103cc5760405162461bcd60e51b815260040161034791906107e6565b50506001600160a01b0392831660009081526003602090815260408083209490951682529290925291902055600190565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146104465760405162461bcd60e51b815260040161034791906107e6565b50600180546001600160a01b0319166001600160a01b0392909216919091179055565b60015460408051808201909152600681526532353030303160d01b6020820152906001600160a01b031633146104b25760405162461bcd60e51b815260040161034791906107e6565b50600097885260046020819052604090982080546001600160a01b039889166001600160a01b0319918216178255600182018054988a169882169890981790975560028101805496891696909716959095179095556003840192909255919094018054921515600160a81b0260ff60a81b19951515600160a01b026001600160a81b031990941692909416919091179190911792909216179055565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146105975760405162461bcd60e51b815260040161034791906107e6565b5060408051808201909152600681526535303031303160d01b60208201526001600160a01b0382166105dc5760405162461bcd60e51b815260040161034791906107e6565b50600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60015460408051808201909152600681526532353030303160d01b6020820152906001600160a01b031633146106815760405162461bcd60e51b815260040161034791906107e6565b50600555565b80356001600160a01b038116811461069e57600080fd5b919050565b600080604083850312156106b657600080fd5b6106bf83610687565b91506106cd60208401610687565b90509250929050565b6000806000606084860312156106eb57600080fd5b6106f484610687565b925061070260208501610687565b9150604084013590509250925092565b60006020828403121561072457600080fd5b61072d82610687565b9392505050565b60006020828403121561074657600080fd5b5035919050565b8035801515811461069e57600080fd5b600080600080600080600080610100898b03121561077a57600080fd5b8835975061078a60208a01610687565b965061079860408a01610687565b95506107a660608a01610687565b9450608089013593506107bb60a08a01610687565b92506107c960c08a0161074d565b91506107d760e08a0161074d565b90509295985092959890939650565b60006020808352835180602085015260005b81811015610814578581018301518582016040015282016107f8565b506000604082860101526040601f19601f830116850101925050509291505056fea26469706673582212204889423730a418bf1a26edf713979d543ae8c11a38568eeecfa7ddf5920b0f9664736f6c63430008170033",
+ "deployedBytecode": "608060405234801561001057600080fd5b50600436106100cf5760003560e01c8063d04c23af1161008c578063de8211a911610066578063de8211a914610215578063ecf89597146102c3578063f2fde38b146102d6578063fd44b92e146102e957600080fd5b8063d04c23af146101b4578063d28eb963146101c7578063d4fac45d146101dc57600080fd5b8063097d9012146100d45780638da5cb5b1461012057806399933b331461014b578063adb6f63f14610153578063b5c9cbbe1461017e578063c07f47d4146101a1575b600080fd5b61010d6100e23660046106a3565b6001600160a01b03918216600090815260036020908152604080832093909416825291909152205490565b6040519081526020015b60405180910390f35b600054610133906001600160a01b031681565b6040516001600160a01b039091168152602001610117565b60055461010d565b61010d6101613660046106a3565b600360209081526000928352604080842090915290825290205481565b61019161018c3660046106d6565b6102fc565b6040519015158152602001610117565b600154610133906001600160a01b031681565b6101916101c23660046106d6565b610381565b6101da6101d5366004610712565b6103fd565b005b61010d6101ea3660046106a3565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b610278610223366004610734565b6000908152600460208190526040909120805460018201546002830154600384015493909401546001600160a01b0392831695918316948316939281169160ff600160a01b8304811692600160a81b90041690565b604080516001600160a01b0398891681529688166020880152948716948601949094526060850192909252909316608083015291151560a082015290151560c082015260e001610117565b6101da6102d136600461075d565b610469565b6101da6102e4366004610712565b61054e565b6101da6102f7366004610734565b610638565b60015460408051808201909152600681526532353030303160d01b60208201526000916001600160a01b031633146103505760405162461bcd60e51b815260040161034791906107e6565b60405180910390fd5b50506001600160a01b0392831660009081526002602090815260408083209490951682529290925291902055600190565b60015460408051808201909152600681526532353030303160d01b60208201526000916001600160a01b031633146103cc5760405162461bcd60e51b815260040161034791906107e6565b50506001600160a01b0392831660009081526003602090815260408083209490951682529290925291902055600190565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146104465760405162461bcd60e51b815260040161034791906107e6565b50600180546001600160a01b0319166001600160a01b0392909216919091179055565b60015460408051808201909152600681526532353030303160d01b6020820152906001600160a01b031633146104b25760405162461bcd60e51b815260040161034791906107e6565b50600097885260046020819052604090982080546001600160a01b039889166001600160a01b0319918216178255600182018054988a169882169890981790975560028101805496891696909716959095179095556003840192909255919094018054921515600160a81b0260ff60a81b19951515600160a01b026001600160a81b031990941692909416919091179190911792909216179055565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146105975760405162461bcd60e51b815260040161034791906107e6565b5060408051808201909152600681526535303031303160d01b60208201526001600160a01b0382166105dc5760405162461bcd60e51b815260040161034791906107e6565b50600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60015460408051808201909152600681526532353030303160d01b6020820152906001600160a01b031633146106815760405162461bcd60e51b815260040161034791906107e6565b50600555565b80356001600160a01b038116811461069e57600080fd5b919050565b600080604083850312156106b657600080fd5b6106bf83610687565b91506106cd60208401610687565b90509250929050565b6000806000606084860312156106eb57600080fd5b6106f484610687565b925061070260208501610687565b9150604084013590509250925092565b60006020828403121561072457600080fd5b61072d82610687565b9392505050565b60006020828403121561074657600080fd5b5035919050565b8035801515811461069e57600080fd5b600080600080600080600080610100898b03121561077a57600080fd5b8835975061078a60208a01610687565b965061079860408a01610687565b95506107a660608a01610687565b9450608089013593506107bb60a08a01610687565b92506107c960c08a0161074d565b91506107d760e08a0161074d565b90509295985092959890939650565b60006020808352835180602085015260005b81811015610814578581018301518582016040015282016107f8565b506000604082860101526040601f19601f830116850101925050509291505056fea26469706673582212204889423730a418bf1a26edf713979d543ae8c11a38568eeecfa7ddf5920b0f9664736f6c63430008170033"
+}
\ No newline at end of file
diff --git a/contracts/IbetSecurityTokenDVP.json b/contracts/IbetSecurityTokenDVP.json
new file mode 100644
index 00000000..5f835cbf
--- /dev/null
+++ b/contracts/IbetSecurityTokenDVP.json
@@ -0,0 +1,651 @@
+{
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_storageAddress",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "deliveryId",
+ "type": "uint256"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "seller",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "buyer",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "agent",
+ "type": "address"
+ }
+ ],
+ "name": "DeliveryAborted",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "deliveryId",
+ "type": "uint256"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "seller",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "buyer",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "agent",
+ "type": "address"
+ }
+ ],
+ "name": "DeliveryCanceled",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "deliveryId",
+ "type": "uint256"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "seller",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "buyer",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "agent",
+ "type": "address"
+ }
+ ],
+ "name": "DeliveryConfirmed",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "deliveryId",
+ "type": "uint256"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "seller",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "buyer",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "agent",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "string",
+ "name": "data",
+ "type": "string"
+ }
+ ],
+ "name": "DeliveryCreated",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "deliveryId",
+ "type": "uint256"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "seller",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "buyer",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "agent",
+ "type": "address"
+ }
+ ],
+ "name": "DeliveryFinished",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "Deposited",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "HolderChanged",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "previousOwner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "newOwner",
+ "type": "address"
+ }
+ ],
+ "name": "OwnershipTransferred",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "Withdrawn",
+ "type": "event"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "_deliveryId",
+ "type": "uint256"
+ }
+ ],
+ "name": "abortDelivery",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_account",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "_token",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256[]",
+ "name": "_deliveryIdList",
+ "type": "uint256[]"
+ }
+ ],
+ "name": "bulkFinishDelivery",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "success",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "_deliveryId",
+ "type": "uint256"
+ }
+ ],
+ "name": "cancelDelivery",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_account",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "_token",
+ "type": "address"
+ }
+ ],
+ "name": "commitmentOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "_deliveryId",
+ "type": "uint256"
+ }
+ ],
+ "name": "confirmDelivery",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_token",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "_buyer",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "_agent",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "_data",
+ "type": "string"
+ }
+ ],
+ "name": "createDelivery",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "_deliveryId",
+ "type": "uint256"
+ }
+ ],
+ "name": "finishDelivery",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "_deliveryId",
+ "type": "uint256"
+ }
+ ],
+ "name": "getDelivery",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "seller",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "buyer",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "agent",
+ "type": "address"
+ },
+ {
+ "internalType": "bool",
+ "name": "confirmed",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "valid",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "latestDeliveryId",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "owner",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "storageAddress",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_from",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_value",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "",
+ "type": "bytes"
+ }
+ ],
+ "name": "tokenFallback",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "newOwner",
+ "type": "address"
+ }
+ ],
+ "name": "transferOwnership",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_token",
+ "type": "address"
+ }
+ ],
+ "name": "withdraw",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+ ],
+ "bytecode": "60806040523480156200001157600080fd5b506040516200257f3803806200257f833981016040819052620000349162000068565b60008054336001600160a01b031991821617909155600180549091166001600160a01b03929092169190911790556200009a565b6000602082840312156200007b57600080fd5b81516001600160a01b03811681146200009357600080fd5b9392505050565b6124d580620000aa6000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c8063b62549af11610097578063de8211a911610066578063de8211a9146101fd578063f2fde38b1461025b578063f7888aec1461026e578063fd84cb971461028157600080fd5b8063b62549af146101af578063c0a36f8a146101c2578063c0ee0b8a146101d5578063da5f7c45146101ea57600080fd5b806385aa92a7116100d357806385aa92a71461014b5780638da5cb5b14610176578063a2ee704314610189578063b4d904761461019c57600080fd5b806309326794146100fa57806351cff8d9146101155780636a4c76f814610138575b600080fd5b610102610294565b6040519081526020015b60405180910390f35b610128610123366004611fcc565b610307565b604051901515815260200161010c565b610128610146366004611ff0565b61048b565b60015461015e906001600160a01b031681565b6040516001600160a01b03909116815260200161010c565b60005461015e906001600160a01b031681565b610102610197366004612009565b610a9a565b6101286101aa366004611ff0565b610b1b565b6101286101bd366004611ff0565b610f94565b6101026101d03660046120ce565b6113e0565b6101e86101e3366004612161565b611854565b005b6101286101f83660046121ce565b611912565b61021061020b366004611ff0565b611950565b604080516001600160a01b0398891681529688166020880152948716948601949094526060850192909252909316608083015291151560a082015290151560c082015260e00161010c565b6101e8610269366004611fcc565b6119e1565b61010261027c366004612009565b611acb565b61012861028f366004611ff0565b611b06565b600154604080516399933b3360e01b815290516000926001600160a01b0316916399933b339160048083019260209291908290030181865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190612243565b905090565b6000806103143384611acb565b9050600081116040518060400160405280600681526020016532363035303160d01b815250906103605760405162461bcd60e51b815260040161035791906122a2565b60405180910390fd5b5060405163a9059cbb60e01b8152336004820152602481018290526001600160a01b0384169063a9059cbb906044016020604051808303816000875af11580156103ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d291906122ca565b50600154604051635ae4e5df60e11b81526001600160a01b039091169063b5c9cbbe9061040890339087906000906004016122e5565b6020604051808303816000875af1158015610427573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044b91906122ca565b5060405133906001600160a01b038516907f85b9d5ac4b95740dafd1b47130d38b5f34a9104dd14b1c88a2fb5a44c3a00ce790600090a350600192915050565b600154604080516399933b3360e01b815290516000926001600160a01b0316916399933b339160048083019260209291908290030181865afa1580156104d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f99190612243565b8211156040518060400160405280600681526020016532363033303160d01b815250906105395760405162461bcd60e51b815260040161035791906122a2565b50610542611f78565b60015460405163de8211a960e01b8152600481018590526001600160a01b039091169063de8211a99060240160e060405180830381865afa15801561058b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105af9190612309565b151560c0880181905290151560a08801526001600160a01b039182166080880152606087019290925291821660408087019190915292821660208087019190915293909116845281518083019092526006825265191b1819981960d11b92820192909252906001146106345760405162461bcd60e51b815260040161035791906122a2565b5060a081015160408051808201909152600681526532363033303360d01b602082015290151560011461067a5760405162461bcd60e51b815260040161035791906122a2565b5060808101516040805180820190915260068152650c8d8c0ccc0d60d21b6020820152906001600160a01b031633146106c65760405162461bcd60e51b815260040161035791906122a2565b5080600001516001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610709573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072d91906122ca565b60408051808201909152600681526532363033303560d01b602082015290151560011461076d5760405162461bcd60e51b815260040161035791906122a2565b5080600001516001600160a01b0316636f3b993f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d491906122ca565b604080518082019091526006815265191b1819981b60d11b602082015290156108105760405162461bcd60e51b815260040161035791906122a2565b506001546040820151825160608401516001600160a01b039093169263b5c9cbbe929190610848906108428484611acb565b90611f60565b6040518463ffffffff1660e01b8152600401610866939291906122e5565b6020604051808303816000875af1158015610885573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a991906122ca565b506001546020820151825160608401516001600160a01b039093169263d04c23af9291906108e1906108db8484610a9a565b90611f6c565b6040518463ffffffff1660e01b81526004016108ff939291906122e5565b6020604051808303816000875af115801561091e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094291906122ca565b50600154815160208301516040808501516060860151608087015160a0880151935163ecf8959760e01b81526001600160a01b039097169663ecf895979661099c968c969195909490939092909190600090600401612393565b600060405180830381600087803b1580156109b657600080fd5b505af11580156109ca573d6000803e3d6000fd5b5050505080600001516001600160a01b0316837fae13fd5bb7db89e0f8059ff395d808a71fc16b9ea25a1e8be803f1419575902e8360200151846040015185606001518660800151604051610a2294939291906123dc565b60405180910390a380604001516001600160a01b031681602001516001600160a01b031682600001516001600160a01b03167f2458504403156ef04185b3cb0aab362f0421374a9fccb513fcf87c416324d40e8460600151604051610a8991815260200190565b60405180910390a450600192915050565b6001546040516304bec80960e11b81526001600160a01b0384811660048301528381166024830152600092169063097d9012906044015b602060405180830381865afa158015610aee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b129190612243565b90505b92915050565b600154604080516399933b3360e01b815290516000926001600160a01b0316916399933b339160048083019260209291908290030181865afa158015610b65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b899190612243565b8211156040518060400160405280600681526020016532363031303160d01b81525090610bc95760405162461bcd60e51b815260040161035791906122a2565b50610bd2611f78565b60015460405163de8211a960e01b8152600481018590526001600160a01b039091169063de8211a99060240160e060405180830381865afa158015610c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3f9190612309565b151560c0880181905290151560a08801526001600160a01b039182166080880152606087019290925291821660408087019190915292821660208087019190915293909116845281518083019092526006825265191b1818981960d11b9282019290925290600114610cc45760405162461bcd60e51b815260040161035791906122a2565b5060a081015160408051808201909152600681526532363031303360d01b60208201529015610d065760405162461bcd60e51b815260040161035791906122a2565b5080602001516001600160a01b0316336001600160a01b03161480610d40575080604001516001600160a01b0316336001600160a01b0316145b604051806040016040528060068152602001650c8d8c0c4c0d60d21b81525090610d7d5760405162461bcd60e51b815260040161035791906122a2565b506001546020820151825160608401516001600160a01b039093169263b5c9cbbe929190610daf906108428484611acb565b6040518463ffffffff1660e01b8152600401610dcd939291906122e5565b6020604051808303816000875af1158015610dec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1091906122ca565b506001546020820151825160608401516001600160a01b039093169263d04c23af929190610e42906108db8484610a9a565b6040518463ffffffff1660e01b8152600401610e60939291906122e5565b6020604051808303816000875af1158015610e7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea391906122ca565b50600154815160208301516040808501516060860151608087015160a0880151935163ecf8959760e01b81526001600160a01b039097169663ecf8959796610efd968c969195909490939092909190600090600401612393565b600060405180830381600087803b158015610f1757600080fd5b505af1158015610f2b573d6000803e3d6000fd5b5050505080600001516001600160a01b0316837f83f6050bab67e325a246d7c944af50a51620253dcae7243de09efa23b2fb52238360200151846040015185606001518660800151604051610f8394939291906123dc565b60405180910390a350600192915050565b600154604080516399933b3360e01b815290516000926001600160a01b0316916399933b339160048083019260209291908290030181865afa158015610fde573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110029190612243565b8211156040518060400160405280600681526020016532363034303160d01b815250906110425760405162461bcd60e51b815260040161035791906122a2565b5061104b611f78565b60015460405163de8211a960e01b8152600481018590526001600160a01b039091169063de8211a99060240160e060405180830381865afa158015611094573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b89190612309565b151560c0880181905290151560a08801526001600160a01b039182166080880152606087019290925291821660408087019190915292821660208087019190915293909116845281518083019092526006825265191b181a181960d11b928201929092529060011461113d5760405162461bcd60e51b815260040161035791906122a2565b5060a081015160408051808201909152600681526532363034303360d01b60208201529015156001146111835760405162461bcd60e51b815260040161035791906122a2565b5080608001516001600160a01b0316336001600160a01b031614604051806040016040528060068152602001650c8d8c0d0c0d60d21b815250906111da5760405162461bcd60e51b815260040161035791906122a2565b506001546020820151825160608401516001600160a01b039093169263b5c9cbbe92919061120c906108428484611acb565b6040518463ffffffff1660e01b815260040161122a939291906122e5565b6020604051808303816000875af1158015611249573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126d91906122ca565b506001546020820151825160608401516001600160a01b039093169263d04c23af92919061129f906108db8484610a9a565b6040518463ffffffff1660e01b81526004016112bd939291906122e5565b6020604051808303816000875af11580156112dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130091906122ca565b50600154815160208301516040808501516060860151608087015160a0880151935163ecf8959760e01b81526001600160a01b039097169663ecf895979661135a968c969195909490939092909190600090600401612393565b600060405180830381600087803b15801561137457600080fd5b505af1158015611388573d6000803e3d6000fd5b5050505080600001516001600160a01b0316837f37c971bd668c8d1b347a40a1db0d7338d910adcf4d93dc7f8a95b468ddda58828360200151846040015185606001518660800151604051610f8394939291906123dc565b60008084116040518060400160405280600681526020016532363030303160d01b815250906114225760405162461bcd60e51b815260040161035791906122a2565b508361142e3388611acb565b101560405180604001604052806006815260200165191b1818181960d11b8152509061146d5760405162461bcd60e51b815260040161035791906122a2565b50856001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d091906122ca565b60408051808201909152600681526532363030303360d01b60208201529015156001146115105760405162461bcd60e51b815260040161035791906122a2565b50856001600160a01b0316636f3b993f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561154f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157391906122ca565b6040805180820190915260068152650c8d8c0c0c0d60d21b602082015290156115af5760405162461bcd60e51b815260040161035791906122a2565b50600154604080516399933b3360e01b815290516000926001600160a01b0316916399933b339160048083019260209291908290030181865afa1580156115fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161e9190612243565b61162990600161241d565b600154604051637ea25c9760e11b8152600481018390529192506001600160a01b03169063fd44b92e90602401600060405180830381600087803b15801561167057600080fd5b505af1158015611684573d6000803e3d6000fd5b50506001805460405163ecf8959760e01b81526001600160a01b03909116935063ecf8959792506116c69185918c9133918d918d918d91600091600401612393565b600060405180830381600087803b1580156116e057600080fd5b505af11580156116f4573d6000803e3d6000fd5b50506001546001600160a01b0316915063b5c9cbbe9050338961171b896108db8484611acb565b6040518463ffffffff1660e01b8152600401611739939291906122e5565b6020604051808303816000875af1158015611758573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061177c91906122ca565b506001546001600160a01b031663d04c23af338961179e896108428484610a9a565b6040518463ffffffff1660e01b81526004016117bc939291906122e5565b6020604051808303816000875af11580156117db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117ff91906122ca565b50866001600160a01b0316817f4a2cf5c0983fc0948d3f0751b04bdf091d03d7a1a5d757d1c93b5a8f2f295f413389898989604051611842959493929190612430565b60405180910390a39695505050505050565b6001546001600160a01b031663b5c9cbbe8433611875866108428484611acb565b6040518463ffffffff1660e01b8152600401611893939291906122e5565b6020604051808303816000875af11580156118b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118d691906122ca565b506040516001600160a01b0384169033907f76dacbd9b11b7bbe3372e54b4adc1eeb5724ff92f91142a1a45722c28582ebfd90600090a3505050565b6000805b828110156119495761193f84848381811061193357611933612476565b9050602002013561048b565b9150600101611916565b5092915050565b60015460405163de8211a960e01b8152600481018390526000918291829182918291829182916001600160a01b03169063de8211a99060240160e060405180830381865afa1580156119a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ca9190612309565b959e949d50929b5090995097509550909350915050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611a2a5760405162461bcd60e51b815260040161035791906122a2565b5060408051808201909152600681526535303031303160d01b60208201526001600160a01b038216611a6f5760405162461bcd60e51b815260040161035791906122a2565b50600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60015460405163d4fac45d60e01b81526001600160a01b0384811660048301528381166024830152600092169063d4fac45d90604401610ad1565b600154604080516399933b3360e01b815290516000926001600160a01b0316916399933b339160048083019260209291908290030181865afa158015611b50573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b749190612243565b8211156040518060400160405280600681526020016532363032303160d01b81525090611bb45760405162461bcd60e51b815260040161035791906122a2565b50611bbd611f78565b60015460405163de8211a960e01b8152600481018590526001600160a01b039091169063de8211a99060240160e060405180830381865afa158015611c06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c2a9190612309565b151560c0880181905290151560a08801526001600160a01b039182166080880152606087019290925291821660408087019190915292821660208087019190915293909116845281518083019092526006825265191b1819181960d11b9282019290925290600114611caf5760405162461bcd60e51b815260040161035791906122a2565b5060a081015160408051808201909152600681526532363032303360d01b60208201529015611cf15760405162461bcd60e51b815260040161035791906122a2565b50604081810151815180830190925260068252650c8d8c0c8c0d60d21b60208301526001600160a01b03163314611d3b5760405162461bcd60e51b815260040161035791906122a2565b5080600001516001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611da291906122ca565b60408051808201909152600681526532363032303560d01b6020820152901515600114611de25760405162461bcd60e51b815260040161035791906122a2565b5080600001516001600160a01b0316636f3b993f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4991906122ca565b604080518082019091526006815265191b1819181b60d11b60208201529015611e855760405162461bcd60e51b815260040161035791906122a2565b5060018054825160208401516040808601516060870151608088015160c0890151935163ecf8959760e01b81526001600160a01b039097169763ecf8959797611eda978d979096909594939291600401612393565b600060405180830381600087803b158015611ef457600080fd5b505af1158015611f08573d6000803e3d6000fd5b5050505080600001516001600160a01b0316837ffa1e4d4f57c605169fce32ba32e2fd705e590b8337ad5a79c677440230e4482d8360200151846040015185606001518660800151604051610f8394939291906123dc565b6000610b12828461241d565b6000610b12828461248c565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b6001600160a01b0381168114611fc957600080fd5b50565b600060208284031215611fde57600080fd5b8135611fe981611fb4565b9392505050565b60006020828403121561200257600080fd5b5035919050565b6000806040838503121561201c57600080fd5b823561202781611fb4565b9150602083013561203781611fb4565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff8084111561207357612073612042565b604051601f8501601f19908116603f0116810190828211818310171561209b5761209b612042565b816040528093508581528686860111156120b457600080fd5b858560208301376000602087830101525050509392505050565b600080600080600060a086880312156120e657600080fd5b85356120f181611fb4565b9450602086013561210181611fb4565b935060408601359250606086013561211881611fb4565b9150608086013567ffffffffffffffff81111561213457600080fd5b8601601f8101881361214557600080fd5b61215488823560208401612058565b9150509295509295909350565b60008060006060848603121561217657600080fd5b833561218181611fb4565b925060208401359150604084013567ffffffffffffffff8111156121a457600080fd5b8401601f810186136121b557600080fd5b6121c486823560208401612058565b9150509250925092565b600080602083850312156121e157600080fd5b823567ffffffffffffffff808211156121f957600080fd5b818501915085601f83011261220d57600080fd5b81358181111561221c57600080fd5b8660208260051b850101111561223157600080fd5b60209290920196919550909350505050565b60006020828403121561225557600080fd5b5051919050565b6000815180845260005b8181101561228257602081850181015186830182015201612266565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000610b12602083018461225c565b805180151581146122c557600080fd5b919050565b6000602082840312156122dc57600080fd5b610b12826122b5565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600080600080600080600060e0888a03121561232457600080fd5b875161232f81611fb4565b602089015190975061234081611fb4565b604089015190965061235181611fb4565b606089015160808a0151919650945061236981611fb4565b925061237760a089016122b5565b915061238560c089016122b5565b905092959891949750929550565b9788526001600160a01b03968716602089015294861660408801529285166060870152608086019190915290921660a084015290151560c0830152151560e08201526101000190565b6001600160a01b03948516815292841660208401526040830191909152909116606082015260800190565b634e487b7160e01b600052601160045260246000fd5b80820180821115610b1557610b15612407565b6001600160a01b0386811682528581166020830152604082018590528316606082015260a06080820181905260009061246b9083018461225c565b979650505050505050565b634e487b7160e01b600052603260045260246000fd5b81810381811115610b1557610b1561240756fea264697066735822122057d989c84f5a6d77f74e97300e91e6e78cca2d3270dca8553354c5bf221ba45064736f6c63430008170033",
+ "deployedBytecode": "608060405234801561001057600080fd5b50600436106100f55760003560e01c8063b62549af11610097578063de8211a911610066578063de8211a9146101fd578063f2fde38b1461025b578063f7888aec1461026e578063fd84cb971461028157600080fd5b8063b62549af146101af578063c0a36f8a146101c2578063c0ee0b8a146101d5578063da5f7c45146101ea57600080fd5b806385aa92a7116100d357806385aa92a71461014b5780638da5cb5b14610176578063a2ee704314610189578063b4d904761461019c57600080fd5b806309326794146100fa57806351cff8d9146101155780636a4c76f814610138575b600080fd5b610102610294565b6040519081526020015b60405180910390f35b610128610123366004611fcc565b610307565b604051901515815260200161010c565b610128610146366004611ff0565b61048b565b60015461015e906001600160a01b031681565b6040516001600160a01b03909116815260200161010c565b60005461015e906001600160a01b031681565b610102610197366004612009565b610a9a565b6101286101aa366004611ff0565b610b1b565b6101286101bd366004611ff0565b610f94565b6101026101d03660046120ce565b6113e0565b6101e86101e3366004612161565b611854565b005b6101286101f83660046121ce565b611912565b61021061020b366004611ff0565b611950565b604080516001600160a01b0398891681529688166020880152948716948601949094526060850192909252909316608083015291151560a082015290151560c082015260e00161010c565b6101e8610269366004611fcc565b6119e1565b61010261027c366004612009565b611acb565b61012861028f366004611ff0565b611b06565b600154604080516399933b3360e01b815290516000926001600160a01b0316916399933b339160048083019260209291908290030181865afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103029190612243565b905090565b6000806103143384611acb565b9050600081116040518060400160405280600681526020016532363035303160d01b815250906103605760405162461bcd60e51b815260040161035791906122a2565b60405180910390fd5b5060405163a9059cbb60e01b8152336004820152602481018290526001600160a01b0384169063a9059cbb906044016020604051808303816000875af11580156103ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d291906122ca565b50600154604051635ae4e5df60e11b81526001600160a01b039091169063b5c9cbbe9061040890339087906000906004016122e5565b6020604051808303816000875af1158015610427573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044b91906122ca565b5060405133906001600160a01b038516907f85b9d5ac4b95740dafd1b47130d38b5f34a9104dd14b1c88a2fb5a44c3a00ce790600090a350600192915050565b600154604080516399933b3360e01b815290516000926001600160a01b0316916399933b339160048083019260209291908290030181865afa1580156104d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f99190612243565b8211156040518060400160405280600681526020016532363033303160d01b815250906105395760405162461bcd60e51b815260040161035791906122a2565b50610542611f78565b60015460405163de8211a960e01b8152600481018590526001600160a01b039091169063de8211a99060240160e060405180830381865afa15801561058b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105af9190612309565b151560c0880181905290151560a08801526001600160a01b039182166080880152606087019290925291821660408087019190915292821660208087019190915293909116845281518083019092526006825265191b1819981960d11b92820192909252906001146106345760405162461bcd60e51b815260040161035791906122a2565b5060a081015160408051808201909152600681526532363033303360d01b602082015290151560011461067a5760405162461bcd60e51b815260040161035791906122a2565b5060808101516040805180820190915260068152650c8d8c0ccc0d60d21b6020820152906001600160a01b031633146106c65760405162461bcd60e51b815260040161035791906122a2565b5080600001516001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610709573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072d91906122ca565b60408051808201909152600681526532363033303560d01b602082015290151560011461076d5760405162461bcd60e51b815260040161035791906122a2565b5080600001516001600160a01b0316636f3b993f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d491906122ca565b604080518082019091526006815265191b1819981b60d11b602082015290156108105760405162461bcd60e51b815260040161035791906122a2565b506001546040820151825160608401516001600160a01b039093169263b5c9cbbe929190610848906108428484611acb565b90611f60565b6040518463ffffffff1660e01b8152600401610866939291906122e5565b6020604051808303816000875af1158015610885573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a991906122ca565b506001546020820151825160608401516001600160a01b039093169263d04c23af9291906108e1906108db8484610a9a565b90611f6c565b6040518463ffffffff1660e01b81526004016108ff939291906122e5565b6020604051808303816000875af115801561091e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094291906122ca565b50600154815160208301516040808501516060860151608087015160a0880151935163ecf8959760e01b81526001600160a01b039097169663ecf895979661099c968c969195909490939092909190600090600401612393565b600060405180830381600087803b1580156109b657600080fd5b505af11580156109ca573d6000803e3d6000fd5b5050505080600001516001600160a01b0316837fae13fd5bb7db89e0f8059ff395d808a71fc16b9ea25a1e8be803f1419575902e8360200151846040015185606001518660800151604051610a2294939291906123dc565b60405180910390a380604001516001600160a01b031681602001516001600160a01b031682600001516001600160a01b03167f2458504403156ef04185b3cb0aab362f0421374a9fccb513fcf87c416324d40e8460600151604051610a8991815260200190565b60405180910390a450600192915050565b6001546040516304bec80960e11b81526001600160a01b0384811660048301528381166024830152600092169063097d9012906044015b602060405180830381865afa158015610aee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b129190612243565b90505b92915050565b600154604080516399933b3360e01b815290516000926001600160a01b0316916399933b339160048083019260209291908290030181865afa158015610b65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b899190612243565b8211156040518060400160405280600681526020016532363031303160d01b81525090610bc95760405162461bcd60e51b815260040161035791906122a2565b50610bd2611f78565b60015460405163de8211a960e01b8152600481018590526001600160a01b039091169063de8211a99060240160e060405180830381865afa158015610c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3f9190612309565b151560c0880181905290151560a08801526001600160a01b039182166080880152606087019290925291821660408087019190915292821660208087019190915293909116845281518083019092526006825265191b1818981960d11b9282019290925290600114610cc45760405162461bcd60e51b815260040161035791906122a2565b5060a081015160408051808201909152600681526532363031303360d01b60208201529015610d065760405162461bcd60e51b815260040161035791906122a2565b5080602001516001600160a01b0316336001600160a01b03161480610d40575080604001516001600160a01b0316336001600160a01b0316145b604051806040016040528060068152602001650c8d8c0c4c0d60d21b81525090610d7d5760405162461bcd60e51b815260040161035791906122a2565b506001546020820151825160608401516001600160a01b039093169263b5c9cbbe929190610daf906108428484611acb565b6040518463ffffffff1660e01b8152600401610dcd939291906122e5565b6020604051808303816000875af1158015610dec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1091906122ca565b506001546020820151825160608401516001600160a01b039093169263d04c23af929190610e42906108db8484610a9a565b6040518463ffffffff1660e01b8152600401610e60939291906122e5565b6020604051808303816000875af1158015610e7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea391906122ca565b50600154815160208301516040808501516060860151608087015160a0880151935163ecf8959760e01b81526001600160a01b039097169663ecf8959796610efd968c969195909490939092909190600090600401612393565b600060405180830381600087803b158015610f1757600080fd5b505af1158015610f2b573d6000803e3d6000fd5b5050505080600001516001600160a01b0316837f83f6050bab67e325a246d7c944af50a51620253dcae7243de09efa23b2fb52238360200151846040015185606001518660800151604051610f8394939291906123dc565b60405180910390a350600192915050565b600154604080516399933b3360e01b815290516000926001600160a01b0316916399933b339160048083019260209291908290030181865afa158015610fde573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110029190612243565b8211156040518060400160405280600681526020016532363034303160d01b815250906110425760405162461bcd60e51b815260040161035791906122a2565b5061104b611f78565b60015460405163de8211a960e01b8152600481018590526001600160a01b039091169063de8211a99060240160e060405180830381865afa158015611094573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b89190612309565b151560c0880181905290151560a08801526001600160a01b039182166080880152606087019290925291821660408087019190915292821660208087019190915293909116845281518083019092526006825265191b181a181960d11b928201929092529060011461113d5760405162461bcd60e51b815260040161035791906122a2565b5060a081015160408051808201909152600681526532363034303360d01b60208201529015156001146111835760405162461bcd60e51b815260040161035791906122a2565b5080608001516001600160a01b0316336001600160a01b031614604051806040016040528060068152602001650c8d8c0d0c0d60d21b815250906111da5760405162461bcd60e51b815260040161035791906122a2565b506001546020820151825160608401516001600160a01b039093169263b5c9cbbe92919061120c906108428484611acb565b6040518463ffffffff1660e01b815260040161122a939291906122e5565b6020604051808303816000875af1158015611249573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126d91906122ca565b506001546020820151825160608401516001600160a01b039093169263d04c23af92919061129f906108db8484610a9a565b6040518463ffffffff1660e01b81526004016112bd939291906122e5565b6020604051808303816000875af11580156112dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130091906122ca565b50600154815160208301516040808501516060860151608087015160a0880151935163ecf8959760e01b81526001600160a01b039097169663ecf895979661135a968c969195909490939092909190600090600401612393565b600060405180830381600087803b15801561137457600080fd5b505af1158015611388573d6000803e3d6000fd5b5050505080600001516001600160a01b0316837f37c971bd668c8d1b347a40a1db0d7338d910adcf4d93dc7f8a95b468ddda58828360200151846040015185606001518660800151604051610f8394939291906123dc565b60008084116040518060400160405280600681526020016532363030303160d01b815250906114225760405162461bcd60e51b815260040161035791906122a2565b508361142e3388611acb565b101560405180604001604052806006815260200165191b1818181960d11b8152509061146d5760405162461bcd60e51b815260040161035791906122a2565b50856001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d091906122ca565b60408051808201909152600681526532363030303360d01b60208201529015156001146115105760405162461bcd60e51b815260040161035791906122a2565b50856001600160a01b0316636f3b993f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561154f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157391906122ca565b6040805180820190915260068152650c8d8c0c0c0d60d21b602082015290156115af5760405162461bcd60e51b815260040161035791906122a2565b50600154604080516399933b3360e01b815290516000926001600160a01b0316916399933b339160048083019260209291908290030181865afa1580156115fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161e9190612243565b61162990600161241d565b600154604051637ea25c9760e11b8152600481018390529192506001600160a01b03169063fd44b92e90602401600060405180830381600087803b15801561167057600080fd5b505af1158015611684573d6000803e3d6000fd5b50506001805460405163ecf8959760e01b81526001600160a01b03909116935063ecf8959792506116c69185918c9133918d918d918d91600091600401612393565b600060405180830381600087803b1580156116e057600080fd5b505af11580156116f4573d6000803e3d6000fd5b50506001546001600160a01b0316915063b5c9cbbe9050338961171b896108db8484611acb565b6040518463ffffffff1660e01b8152600401611739939291906122e5565b6020604051808303816000875af1158015611758573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061177c91906122ca565b506001546001600160a01b031663d04c23af338961179e896108428484610a9a565b6040518463ffffffff1660e01b81526004016117bc939291906122e5565b6020604051808303816000875af11580156117db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117ff91906122ca565b50866001600160a01b0316817f4a2cf5c0983fc0948d3f0751b04bdf091d03d7a1a5d757d1c93b5a8f2f295f413389898989604051611842959493929190612430565b60405180910390a39695505050505050565b6001546001600160a01b031663b5c9cbbe8433611875866108428484611acb565b6040518463ffffffff1660e01b8152600401611893939291906122e5565b6020604051808303816000875af11580156118b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118d691906122ca565b506040516001600160a01b0384169033907f76dacbd9b11b7bbe3372e54b4adc1eeb5724ff92f91142a1a45722c28582ebfd90600090a3505050565b6000805b828110156119495761193f84848381811061193357611933612476565b9050602002013561048b565b9150600101611916565b5092915050565b60015460405163de8211a960e01b8152600481018390526000918291829182918291829182916001600160a01b03169063de8211a99060240160e060405180830381865afa1580156119a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ca9190612309565b959e949d50929b5090995097509550909350915050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611a2a5760405162461bcd60e51b815260040161035791906122a2565b5060408051808201909152600681526535303031303160d01b60208201526001600160a01b038216611a6f5760405162461bcd60e51b815260040161035791906122a2565b50600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60015460405163d4fac45d60e01b81526001600160a01b0384811660048301528381166024830152600092169063d4fac45d90604401610ad1565b600154604080516399933b3360e01b815290516000926001600160a01b0316916399933b339160048083019260209291908290030181865afa158015611b50573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b749190612243565b8211156040518060400160405280600681526020016532363032303160d01b81525090611bb45760405162461bcd60e51b815260040161035791906122a2565b50611bbd611f78565b60015460405163de8211a960e01b8152600481018590526001600160a01b039091169063de8211a99060240160e060405180830381865afa158015611c06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c2a9190612309565b151560c0880181905290151560a08801526001600160a01b039182166080880152606087019290925291821660408087019190915292821660208087019190915293909116845281518083019092526006825265191b1819181960d11b9282019290925290600114611caf5760405162461bcd60e51b815260040161035791906122a2565b5060a081015160408051808201909152600681526532363032303360d01b60208201529015611cf15760405162461bcd60e51b815260040161035791906122a2565b50604081810151815180830190925260068252650c8d8c0c8c0d60d21b60208301526001600160a01b03163314611d3b5760405162461bcd60e51b815260040161035791906122a2565b5080600001516001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611da291906122ca565b60408051808201909152600681526532363032303560d01b6020820152901515600114611de25760405162461bcd60e51b815260040161035791906122a2565b5080600001516001600160a01b0316636f3b993f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4991906122ca565b604080518082019091526006815265191b1819181b60d11b60208201529015611e855760405162461bcd60e51b815260040161035791906122a2565b5060018054825160208401516040808601516060870151608088015160c0890151935163ecf8959760e01b81526001600160a01b039097169763ecf8959797611eda978d979096909594939291600401612393565b600060405180830381600087803b158015611ef457600080fd5b505af1158015611f08573d6000803e3d6000fd5b5050505080600001516001600160a01b0316837ffa1e4d4f57c605169fce32ba32e2fd705e590b8337ad5a79c677440230e4482d8360200151846040015185606001518660800151604051610f8394939291906123dc565b6000610b12828461241d565b6000610b12828461248c565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b6001600160a01b0381168114611fc957600080fd5b50565b600060208284031215611fde57600080fd5b8135611fe981611fb4565b9392505050565b60006020828403121561200257600080fd5b5035919050565b6000806040838503121561201c57600080fd5b823561202781611fb4565b9150602083013561203781611fb4565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff8084111561207357612073612042565b604051601f8501601f19908116603f0116810190828211818310171561209b5761209b612042565b816040528093508581528686860111156120b457600080fd5b858560208301376000602087830101525050509392505050565b600080600080600060a086880312156120e657600080fd5b85356120f181611fb4565b9450602086013561210181611fb4565b935060408601359250606086013561211881611fb4565b9150608086013567ffffffffffffffff81111561213457600080fd5b8601601f8101881361214557600080fd5b61215488823560208401612058565b9150509295509295909350565b60008060006060848603121561217657600080fd5b833561218181611fb4565b925060208401359150604084013567ffffffffffffffff8111156121a457600080fd5b8401601f810186136121b557600080fd5b6121c486823560208401612058565b9150509250925092565b600080602083850312156121e157600080fd5b823567ffffffffffffffff808211156121f957600080fd5b818501915085601f83011261220d57600080fd5b81358181111561221c57600080fd5b8660208260051b850101111561223157600080fd5b60209290920196919550909350505050565b60006020828403121561225557600080fd5b5051919050565b6000815180845260005b8181101561228257602081850181015186830182015201612266565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000610b12602083018461225c565b805180151581146122c557600080fd5b919050565b6000602082840312156122dc57600080fd5b610b12826122b5565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600080600080600080600060e0888a03121561232457600080fd5b875161232f81611fb4565b602089015190975061234081611fb4565b604089015190965061235181611fb4565b606089015160808a0151919650945061236981611fb4565b925061237760a089016122b5565b915061238560c089016122b5565b905092959891949750929550565b9788526001600160a01b03968716602089015294861660408801529285166060870152608086019190915290921660a084015290151560c0830152151560e08201526101000190565b6001600160a01b03948516815292841660208401526040830191909152909116606082015260800190565b634e487b7160e01b600052601160045260246000fd5b80820180821115610b1557610b15612407565b6001600160a01b0386811682528581166020830152604082018590528316606082015260a06080820181905260009061246b9083018461225c565b979650505050505050565b634e487b7160e01b600052603260045260246000fd5b81810381811115610b1557610b1561240756fea264697066735822122057d989c84f5a6d77f74e97300e91e6e78cca2d3270dca8553354c5bf221ba45064736f6c63430008170033"
+}
\ No newline at end of file
diff --git a/contracts/IbetSecurityTokenInterface.json b/contracts/IbetSecurityTokenInterface.json
index a9618945..7f749462 100644
--- a/contracts/IbetSecurityTokenInterface.json
+++ b/contracts/IbetSecurityTokenInterface.json
@@ -804,6 +804,19 @@
"stateMutability": "nonpayable",
"type": "function"
},
+ {
+ "inputs": [],
+ "name": "requirePersonalInfoRegistered",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -843,6 +856,19 @@
"stateMutability": "nonpayable",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "bool",
+ "name": "_requireRegistered",
+ "type": "bool"
+ }
+ ],
+ "name": "setRequirePersonalInfoRegistered",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
{
"inputs": [
{
diff --git a/contracts/IbetShare.json b/contracts/IbetShare.json
index 444d22e6..4bfb9897 100644
--- a/contracts/IbetShare.json
+++ b/contracts/IbetShare.json
@@ -1045,6 +1045,19 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [],
+ "name": "requirePersonalInfoRegistered",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -1146,6 +1159,19 @@
"stateMutability": "nonpayable",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "bool",
+ "name": "_requireRegistered",
+ "type": "bool"
+ }
+ ],
+ "name": "setRequirePersonalInfoRegistered",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -1371,6 +1397,6 @@
"type": "function"
}
],
- "bytecode": "60806040523480156200001157600080fd5b5060405162003c0b38038062003c0b8339810160408190526200003491620001da565b60008054600160a060020a031916331790556001620000548a826200038a565b5060026200006389826200038a565b5060008054600160a060020a03191633179055600f87905560128190556003869055601485905560156200009885826200038a565b506016620000a784826200038a565b506010620000b683826200038a565b50506013805460ff19908116909155600780549091166001179055505060035460008054600160a060020a0316815260086020526040902055506200045c945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200013d57600080fd5b81516001604060020a03808211156200015a576200015a620000fc565b604051601f8301601f19908116603f01168101908282118183101715620001855762000185620000fc565b81604052838152602092508683858801011115620001a257600080fd5b600091505b83821015620001c65785820183015181830184015290820190620001a7565b600093810190920192909252949350505050565b60008060008060008060008060006101208a8c031215620001fa57600080fd5b89516001604060020a03808211156200021257600080fd5b620002208d838e016200012b565b9a5060208c01519150808211156200023757600080fd5b620002458d838e016200012b565b995060408c0151985060608c0151975060808c0151965060a08c01519150808211156200027157600080fd5b6200027f8d838e016200012b565b955060c08c01519150808211156200029657600080fd5b620002a48d838e016200012b565b945060e08c0151915080821115620002bb57600080fd5b50620002ca8c828d016200012b565b9250506101008a015190509295985092959850929598565b600281046001821680620002f757607f821691505b60208210810362000331577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f82111562000385576000818152602081206020601f86010481016020861015620003605750805b6020601f860104820191505b8181101562000381578281556001016200036c565b5050505b505050565b81516001604060020a03811115620003a657620003a6620000fc565b620003be81620003b78454620002e2565b8462000337565b602080601f831160018114620003fa5760008415620003dd5750858301515b60028086026008870290910a600019041982161786555062000381565b600085815260208120601f198616915b828110156200042b578886015182559484019460019091019084016200040a565b50858210156200044c57878501516008601f88160260020a60001904191681555b5050505050600202600101905550565b61379f806200046c6000396000f3fe608060405234801561001057600080fd5b506004361061035f576000357c01000000000000000000000000000000000000000000000000000000009004806381ebdd79116101d5578063b9b3e06a11610121578063db20266f116100bf578063f2fde38b11610099578063f2fde38b1461073e578063f7502a7c14610751578063fef1b9c014610764578063ff12dcea146107a457600080fd5b8063db20266f146106f3578063e7464db11461071e578063edaab2081461073157600080fd5b8063c7109ec9116100fb578063c7109ec9146106a7578063ca5cbbb5146106ba578063cb761015146106cd578063d9322058146106e057600080fd5b8063b9b3e06a1461066e578063bfe30fb014610681578063c267ce5f1461069457600080fd5b80639301a78b1161018e5780639cd23707116101685780639cd237071461060f578063a9059cbb14610622578063b2a90a6014610635578063b967a52e1461065b57600080fd5b80639301a78b146105d257806395d89b41146105f4578063996f3a4b146105fc57600080fd5b806381ebdd791461056857806383850bcb146105885780638da5cb5b146105905780638db9877c146105a35780638ed8a9bc146105ab57806392ff0d31146105be57600080fd5b806331cef447116102af5780635c2c20051161024d5780636f3b993f116102275780636f3b993f1461052c57806370a082311461053957806376fa7a311461054c5780637da68d341461055f57600080fd5b80635c2c2005146104fd5780635c40f6f4146105065780635ccef3e71461051957600080fd5b806340eba90e1161028957806340eba90e146104c3578063428630f6146104d657806358c3b870146104de5780635b473327146104e657600080fd5b806331cef4471461049557806336f7ab5e146104a857806340615cf8146104b057600080fd5b80631935a8801161031c57806325287d42116102f657806325287d421461043c57806325d608611461044f57806327e235e3146104625780632e027abe1461048257600080fd5b80631935a88014610409578063200d2ed21461041c57806323b872dd1461042957600080fd5b806306eaa0b71461036457806306fdde03146103795780630af7eb0f146103975780630ed5a933146103c2578063153a1f3e146103df57806318160ddd146103f2575b600080fd5b610377610372366004612ed5565b6107b7565b005b610381610ab5565b60405161038e9190612f62565b60405180910390f35b6009546103aa90600160a060020a031681565b604051600160a060020a03909116815260200161038e565b6013546103cf9060ff1681565b604051901515815260200161038e565b6103cf6103ed36600461301d565b610b43565b6103fb60035481565b60405190815260200161038e565b6103776104173660046130e1565b610e06565b6007546103cf9060ff1681565b6103cf6104373660046130fe565b610e9d565b6004546103aa90600160a060020a031681565b61037761045d36600461313a565b6110bd565b6103fb610470366004613177565b60086020526000908152604090205481565b610381610490366004613192565b61111d565b6103776104a3366004612ed5565b611136565b6103816112f9565b6103776104be3660046131b5565b611306565b6103776104d13660046131df565b6113aa565b6103816116cf565b6103816116dc565b6104ee6116e9565b60405161038e93929190613236565b6103fb600f5481565b6103776105143660046130e1565b61180e565b610377610527366004612ed5565b6118a3565b600b546103cf9060ff1681565b6103fb610547366004613177565b611c5f565b61037761055a366004613177565b611c7a565b6103fb60125481565b6103fb610576366004613177565b600d6020526000908152604090205481565b610377611cf9565b6000546103aa90600160a060020a031681565b610381611d81565b6103776105b936600461313a565b611d8e565b6009546103cf9060a060020a900460ff1681565b6105e56105e0366004613177565b611dea565b60405161038e9392919061326b565b610381611e12565b61037761060a366004613293565b611e1f565b61037761061d3660046130e1565b611ed2565b6103cf6106303660046131b5565b611f51565b6009546103cf907501000000000000000000000000000000000000000000900460ff1681565b61037761066936600461313a565b612046565b6103fb61067c3660046132f6565b6120a2565b61037761068f366004613329565b6120cd565b6103776106a23660046131df565b6121d0565b6103776106b53660046130e1565b6122c7565b6103776106c8366004613391565b612384565b6103776106db36600461340a565b6124f3565b6103776106ee36600461313a565b612548565b6103fb6107013660046132f6565b600e60209081526000928352604080842090915290825290205481565b61037761072c3660046130fe565b6125a4565b6017546103cf9060ff1681565b61037761074c366004613177565b6127ac565b61037761075f366004613177565b6128c3565b61077761077236600461340a565b612942565b60408051600160a060020a039586168152949093166020850152918301521515606082015260800161038e565b6103776107b23660046130fe565b61298b565b33600160a060020a0316600c83815481106107d4576107d4613423565b6000918252602090912060049091020154600160a060020a0316148015906108075750600054600160a060020a03163314155b1561086357604080518082018252600681527f31313038303100000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b60405180910390fd5b600c828154811061087657610876613423565b6000918252602082206003600490920201015460ff16151590036108e257604080518082018252600681527f31313038303200000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b600c82815481106108f5576108f5613423565b90600052602060002090600402016002015460086000600c858154811061091e5761091e613423565b60009182526020808320600490920290910154600160a060020a0316835282019290925260400181208054909190610957908490613455565b9091555050600c80548390811061097057610970613423565b906000526020600020906004020160020154600d6000600c858154811061099957610999613423565b60009182526020808320600490920290910154600160a060020a03168352820192909252604001812080549091906109d2908490613468565b925050819055506000600c83815481106109ee576109ee613423565b906000526020600020906004020160030160006101000a81548160ff021916908315150217905550817fa0cc3a4feb26502e6e6cd57b2113d58bdab80c6711d8252356be9a49945bb5f7600c8481548110610a4b57610a4b613423565b6000918252602090912060049091020154600c8054600160a060020a039092169186908110610a7c57610a7c613423565b6000918252602090912060016004909202010154604051610aa99291600160a060020a031690869061347b565b60405180910390a25050565b60018054610ac2906134a7565b80601f0160208091040260200160405190810160405280929190818152602001828054610aee906134a7565b8015610b3b5780601f10610b1057610100808354040283529160200191610b3b565b820191906000526020600020905b815481529060010190602001808311610b1e57829003601f168201915b505050505081565b600b5460009060ff161515600103610ba357604080518082018252600681527f31313035303100000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b8151835114610bfa57604080518082018252600681527f31313035303200000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b6000805b8451811015610c4057838181518110610c1957610c19613423565b602002602001015182610c2c9190613455565b915080610c38816134e4565b915050610bfe565b5080610c4b33611c5f565b1015610c9f57604080518082018252600681527f31313035303300000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b600454600160a060020a03163314610d1a5760095460408051808201909152600681527f313130353034000000000000000000000000000000000000000000000000000060208201529060a060020a900460ff161515600114610d185760405160e560020a62461bcd02815260040161085a9190612f62565b505b606060006001935060005b8651811015610dfb57610d51878281518110610d4357610d43613423565b60200260200101513b151590565b15610d9a57610d93878281518110610d6b57610d6b613423565b6020026020010151878381518110610d8557610d85613423565b602002602001015185612ab9565b9150610dda565b610dd7878281518110610daf57610daf613423565b6020026020010151878381518110610dc957610dc9613423565b602002602001015185612c07565b91505b811515600003610de957600094505b80610df3816134e4565b915050610d25565b505050505b92915050565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a03163314610e555760405160e560020a62461bcd02815260040161085a9190612f62565b50600b805460ff19168215159081179091556040519081527fe1455bc53682229469d6919bb96d7b338cbffea93170dfb5f02242c22fb6d07f9060200160405180910390a150565b60008054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a03163314610eed5760405160e560020a62461bcd02815260040161085a9190612f62565b5081610ef885611c5f565b1015610f4c57604080518082018252600681527f31313036303100000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b6060833b1561102a57610f6883610f6287611c5f565b90612dfc565b600160a060020a038616600090815260086020526040902055610f9483610f8e86611c5f565b90612e0f565b600160a060020a038516600081815260086020526040908190209290925590517fc0ee0b8a00000000000000000000000000000000000000000000000000000000815285919063c0ee0b8a90610ff2903390889087906004016134fd565b600060405180830381600087803b15801561100c57600080fd5b505af1158015611020573d6000803e3d6000fd5b5050505050611077565b61103783610f6287611c5f565b600160a060020a03861660009081526008602052604090205561105d83610f8e86611c5f565b600160a060020a0385166000908152600860205260409020555b83600160a060020a031685600160a060020a031660008051602061374a833981519152856040516110aa91815260200190565b60405180910390a3506001949350505050565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a0316331461110c5760405160e560020a62461bcd02815260040161085a9190612f62565b5060116111198282613574565b5050565b60186020526000908152604090208054610ac2906134a7565b60095460408051808201909152600681527f31313130303100000000000000000000000000000000000000000000000000006020820152907501000000000000000000000000000000000000000000900460ff1615156001146111af5760405160e560020a62461bcd02815260040161085a9190612f62565b506009546000546040517fd3da927f000000000000000000000000000000000000000000000000000000008152336004820152600160a060020a03918216602482015291169063d3da927f90604401602060405180830381865afa15801561121b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123f919061363a565b60408051808201909152600681527f313131303032000000000000000000000000000000000000000000000000000060208201529015156001146112995760405160e560020a62461bcd02815260040161085a9190612f62565b50336000908152600a602052604090208281556002016112b98282613574565b507f3bb9553f633a7ecb4cbc5f9885e750a522496ce06deff1ed9184180ca83940c03383836040516112ed939291906134fd565b60405180910390a15050565b60058054610ac2906134a7565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146113555760405160e560020a62461bcd02815260040161085a9190612f62565b50600160a060020a0382166000818152600a6020908152604091829020600101849055815192835282018390527fa42bd6bdfcb8f9b815c68e4ce0e16dec3f1e7ac53967ee8309653de522a735b191016112ed565b600b5460ff1615806113c6575060095460a060020a900460ff16155b806113d85750816113d633611c5f565b105b1561142b57604080518082018252600681527f31313037303100000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b600054600160a060020a0384811691161461152d576009546000546040517fd3da927f000000000000000000000000000000000000000000000000000000008152600160a060020a038681166004830152918216602482015291169063d3da927f90604401602060405180830381865afa1580156114ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d1919061363a565b60408051808201909152600681527f3131303730320000000000000000000000000000000000000000000000000000602082015290151560011461152b5760405160e560020a62461bcd02815260040161085a9190612f62565b505b336000908152600860205260408120805484929061154c908490613468565b9091555050336000908152600d602052604081208054849290611570908490613455565b9091555050600c80546040805160808101825233808252600160a060020a038881166020840190815283850189815260016060860181815290880189556000989098529351600487027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c78101805492851673ffffffffffffffffffffffffffffffffffffffff1993841617905591517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c8830180549190941691161790915591517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c983015593517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8ca909101805491151560ff1990921691909117905551909182917fa256c3bc72c26fbfd6285cfde8c7e345b4d0c7ccfc725d103e9f129c5d8a039a916116c191889088908890613657565b60405180910390a250505050565b60068054610ac2906134a7565b60118054610ac2906134a7565b60148054601580549192916116fd906134a7565b80601f0160208091040260200160405190810160405280929190818152602001828054611729906134a7565b80156117765780601f1061174b57610100808354040283529160200191611776565b820191906000526020600020905b81548152906001019060200180831161175957829003601f168201915b50505050509080600201805461178b906134a7565b80601f01602080910402602001604051908101604052809291908181526020018280546117b7906134a7565b80156118045780601f106117d957610100808354040283529160200191611804565b820191906000526020600020905b8154815290600101906020018083116117e757829003601f168201915b5050505050905083565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a0316331461185d5760405160e560020a62461bcd02815260040161085a9190612f62565b506007805460ff191682151590811790915560405160ff9091161515907fe1e5c6f5867805bf3fab73f4df4b80d0e87e9262a7bc22ac7c2cb3fd5896222f90600090a250565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146118f25760405160e560020a62461bcd02815260040161085a9190612f62565b5060095460a060020a900460ff16151560000361195757604080518082018252600681527f31313039303100000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b600c828154811061196a5761196a613423565b6000918252602082206003600490920201015460ff16151590036119d657604080518082018252600681527f31313039303200000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b600c82815481106119e9576119e9613423565b90600052602060002090600402016002015460086000600c8581548110611a1257611a12613423565b6000918252602080832060016004909302019190910154600160a060020a0316835282019290925260400181208054909190611a4f908490613455565b9091555050600c805483908110611a6857611a68613423565b906000526020600020906004020160020154600d6000600c8581548110611a9157611a91613423565b60009182526020808320600490920290910154600160a060020a0316835282019290925260400181208054909190611aca908490613468565b925050819055506000600c8381548110611ae657611ae6613423565b906000526020600020906004020160030160006101000a81548160ff021916908315150217905550817f6b50d6e4941ce7ae74ed7f7f51df5fb7680754c2815a094c66bea5ca80a40eb1600c8481548110611b4357611b43613423565b6000918252602090912060049091020154600c8054600160a060020a039092169186908110611b7457611b74613423565b6000918252602090912060016004909202010154604051611ba19291600160a060020a031690869061347b565b60405180910390a2600c8281548110611bbc57611bbc613423565b6000918252602090912060016004909202010154600c8054600160a060020a039092169184908110611bf057611bf0613423565b6000918252602090912060049091020154600c8054600160a060020a039092169160008051602061374a833981519152919086908110611c3257611c32613423565b906000526020600020906004020160020154604051611c5391815260200190565b60405180910390a35050565b600160a060020a031660009081526008602052604090205490565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a03163314611cc95760405160e560020a62461bcd02815260040161085a9190612f62565b506004805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a03163314611d485760405160e560020a62461bcd02815260040161085a9190612f62565b506013805460ff191660011790556040517f8298c3671093b19970d7c94ce1f23925a962f36fec31d25075d9be072b73e10390600090a1565b60108054610ac2906134a7565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a03163314611ddd5760405160e560020a62461bcd02815260040161085a9190612f62565b5060066111198282613574565b600a602052600090815260409020805460018201546002830180549293919261178b906134a7565b60028054610ac2906134a7565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a03163314611e6e5760405160e560020a62461bcd02815260040161085a9190612f62565b5060148390556015611e808382613574565b506016611e8d8282613574565b506014546040517ff89b6034f2b759ebb2dfb08461be917a1b54f2e0523c895e7f9b5e5e14dd013e91611ec591601590601690613705565b60405180910390a1505050565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a03163314611f215760405160e560020a62461bcd02815260040161085a9190612f62565b506009805491151560a060020a0274ff000000000000000000000000000000000000000019909216919091179055565b600081611f5d33611c5f565b10156040518060400160405280600681526020017f313130343031000000000000000000000000000000000000000000000000000081525090611fb65760405160e560020a62461bcd02815260040161085a9190612f62565b5060095460408051808201909152600681527f313130343032000000000000000000000000000000000000000000000000000060208201529060a060020a900460ff16151560011461201e5760405160e560020a62461bcd02815260040161085a9190612f62565b506060833b1561203b57612033848483612ab9565b915050610e00565b612033848483612c07565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146120955760405160e560020a62461bcd02815260040161085a9190612f62565b5060056111198282613574565b600160a060020a039182166000908152600e6020908152604080832093909416825291909152205490565b816120d833866120a2565b101561212c57604080518082018252600681527f31313031303200000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b61213a82610f6233876120a2565b336000908152600e60209081526040808320600160a060020a038916845290915290205561216b82610f8e85611c5f565b600160a060020a038085166000908152600860205260409081902092909255905133918616907f7a1a1088c929a111dda2dc0ca1cc650aa78525d11fd3089abf20c8474f5d82cc906121c2908790879087906134fd565b60405180910390a350505050565b816121da33611c5f565b101561222e57604080518082018252600681527f31313030303200000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b61223b82610f6233611c5f565b3360008181526008602052604090209190915561225f908390610f8e9086906120a2565b600160a060020a0384166000818152600e602090815260408083203380855292529182902093909355519091907ecd77abc69e7bbb6de9df8cbfcca8720df3a30decf9eefd187e72ab2ea2f513906122ba9086908690613730565b60405180910390a3505050565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146123165760405160e560020a62461bcd02815260040161085a9190612f62565b506009805475ff00000000000000000000000000000000000000000019167501000000000000000000000000000000000000000000831515908102919091179091556040517fa0c691180b8089c0c84e478ee67d6325768666cd889f13de016771c6f7af1f8890600090a250565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146123d35760405160e560020a62461bcd02815260040161085a9190612f62565b50816123df86866120a2565b101561243357604080518082018252600681527f31313132303100000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b61244182610f6287876120a2565b600160a060020a038087166000908152600e602090815260408083209389168352929052205561247482610f8e85611c5f565b6008600085600160a060020a0316600160a060020a031681526020019081526020016000208190555084600160a060020a031684600160a060020a03167f7a1a1088c929a111dda2dc0ca1cc650aa78525d11fd3089abf20c8474f5d82cc8585856040516124e4939291906134fd565b60405180910390a35050505050565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146125425760405160e560020a62461bcd02815260040161085a9190612f62565b50601255565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146125975760405160e560020a62461bcd02815260040161085a9190612f62565b5060106111198282613574565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146125f35760405160e560020a62461bcd02815260040161085a9190612f62565b50600160a060020a038216156126ab578061260e83856120a2565b101561266257604080518082018252600681527f31313131303100000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b61267081610f6284866120a2565b600160a060020a038084166000908152600e60209081526040808320938816835292905220556003546126a39082612dfc565b600355612750565b600160a060020a03831660009081526008602052604090205481111561271957604080518082018252600681527f31313131303200000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b61272681610f6285611c5f565b600160a060020a03841660009081526008602052604090205560035461274c9082612dfc565b6003555b81600160a060020a031683600160a060020a031633600160a060020a03167fee02732fab40ece8284c756220846dff4b8d32058b86b35b4f0459bf172fcef08460405161279f91815260200190565b60405180910390a4505050565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146127fb5760405160e560020a62461bcd02815260040161085a9190612f62565b5060408051808201909152600681527f35303031303100000000000000000000000000000000000000000000000000006020820152600160a060020a03821661285a5760405160e560020a62461bcd02815260040161085a9190612f62565b5060008054604051600160a060020a03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146129125760405160e560020a62461bcd02815260040161085a9190612f62565b506009805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600c818154811061295257600080fd5b60009182526020909120600490910201805460018201546002830154600390930154600160a060020a0392831694509116919060ff1684565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146129da5760405160e560020a62461bcd02815260040161085a9190612f62565b50600160a060020a03821615612a33576129f881610f8e84866120a2565b600160a060020a038084166000908152600e6020908152604080832093881683529290522055600354612a2b9082612e0f565b600355612a6a565b612a4081610f8e85611c5f565b600160a060020a038416600090815260086020526040902055600354612a669082612e0f565b6003555b81600160a060020a031683600160a060020a031633600160a060020a03167f65adeb76912378393e600cb6f64f3310842a42e1eae86273dc775d0c47a0f2dc8460405161279f91815260200190565b60045460408051808201909152600681527f31313033303100000000000000000000000000000000000000000000000000006020820152600091600160a060020a03868116911614612b215760405160e560020a62461bcd02815260040161085a9190612f62565b50612b2f83610f6233611c5f565b33600090815260086020526040902055612b4c83610f8e86611c5f565b600160a060020a038516600081815260086020526040908190209290925590517fc0ee0b8a00000000000000000000000000000000000000000000000000000000815285919063c0ee0b8a90612baa903390889088906004016134fd565b600060405180830381600087803b158015612bc457600080fd5b505af1158015612bd8573d6000803e3d6000fd5b5050604051868152600160a060020a038816925033915060008051602061374a833981519152906020016110aa565b600454600090600160a060020a03163314801590612c2c5750600b5460ff1615156001145b15612c7f57604080518082018252600681527f31313032303100000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b600054600160a060020a03858116911614612d81576009546000546040517fd3da927f000000000000000000000000000000000000000000000000000000008152600160a060020a038781166004830152918216602482015291169063d3da927f90604401602060405180830381865afa158015612d01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d25919061363a565b60408051808201909152600681527f31313032303200000000000000000000000000000000000000000000000000006020820152901515600114612d7f5760405160e560020a62461bcd02815260040161085a9190612f62565b505b612d8e83610f6233611c5f565b33600090815260086020526040902055612dab83610f8e86611c5f565b600160a060020a03851660008181526008602052604090819020929092559051339060008051602061374a83398151915290612dea9087815260200190565b60405180910390a35060019392505050565b6000612e088284613468565b9392505050565b6000612e088284613455565b60e060020a634e487b7102600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612e5d57612e5d612e1b565b604052919050565b600082601f830112612e7657600080fd5b813567ffffffffffffffff811115612e9057612e90612e1b565b612ea3601f8201601f1916602001612e34565b818152846020838601011115612eb857600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215612ee857600080fd5b82359150602083013567ffffffffffffffff811115612f0657600080fd5b612f1285828601612e65565b9150509250929050565b6000815180845260005b81811015612f4257602081850181015186830182015201612f26565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000612e086020830184612f1c565b600067ffffffffffffffff821115612f8f57612f8f612e1b565b5060209081020190565b8035600160a060020a0381168114612fb057600080fd5b919050565b600082601f830112612fc657600080fd5b81356020612fdb612fd683612f75565b612e34565b82815291810284018101918181019086841115612ff757600080fd5b8286015b848110156130125780358352918301918301612ffb565b509695505050505050565b6000806040838503121561303057600080fd5b823567ffffffffffffffff8082111561304857600080fd5b818501915085601f83011261305c57600080fd5b8135602061306c612fd683612f75565b8281529181028401810191818101908984111561308857600080fd5b948201945b838610156130ad5761309e86612f99565b8252948201949082019061308d565b965050860135925050808211156130c357600080fd5b50612f1285828601612fb5565b80151581146130de57600080fd5b50565b6000602082840312156130f357600080fd5b8135612e08816130d0565b60008060006060848603121561311357600080fd5b61311c84612f99565b925061312a60208501612f99565b9150604084013590509250925092565b60006020828403121561314c57600080fd5b813567ffffffffffffffff81111561316357600080fd5b61316f84828501612e65565b949350505050565b60006020828403121561318957600080fd5b612e0882612f99565b6000602082840312156131a457600080fd5b813560ff81168114612e0857600080fd5b600080604083850312156131c857600080fd5b6131d183612f99565b946020939093013593505050565b6000806000606084860312156131f457600080fd5b6131fd84612f99565b925060208401359150604084013567ffffffffffffffff81111561322057600080fd5b61322c86828701612e65565b9150509250925092565b83815260606020820152600061324f6060830185612f1c565b82810360408401526132618185612f1c565b9695505050505050565b83815282602082015260606040820152600061328a6060830184612f1c565b95945050505050565b6000806000606084860312156132a857600080fd5b83359250602084013567ffffffffffffffff808211156132c757600080fd5b6132d387838801612e65565b935060408601359150808211156132e957600080fd5b5061322c86828701612e65565b6000806040838503121561330957600080fd5b61331283612f99565b915061332060208401612f99565b90509250929050565b6000806000806080858703121561333f57600080fd5b61334885612f99565b935061335660208601612f99565b925060408501359150606085013567ffffffffffffffff81111561337957600080fd5b61338587828801612e65565b91505092959194509250565b600080600080600060a086880312156133a957600080fd5b6133b286612f99565b94506133c060208701612f99565b93506133ce60408701612f99565b925060608601359150608086013567ffffffffffffffff8111156133f157600080fd5b6133fd88828901612e65565b9150509295509295909350565b60006020828403121561341c57600080fd5b5035919050565b60e060020a634e487b7102600052603260045260246000fd5b60e060020a634e487b7102600052601160045260246000fd5b80820180821115610e0057610e0061343c565b81810381811115610e0057610e0061343c565b6000600160a060020a0380861683528085166020840152506060604083015261328a6060830184612f1c565b6002810460018216806134bb57607f821691505b6020821081036134de5760e060020a634e487b7102600052602260045260246000fd5b50919050565b6000600182016134f6576134f661343c565b5060010190565b600160a060020a038416815282602082015260606040820152600061328a6060830184612f1c565b601f82111561356f576000818152602081206020601f8601048101602086101561354c5750805b6020601f860104820191505b8181101561356b57828155600101613558565b5050505b505050565b815167ffffffffffffffff81111561358e5761358e612e1b565b6135a28161359c84546134a7565b84613525565b602080601f8311600181146135db57600084156135bf5750858301515b60028086026008870290910a600019041982161786555061356b565b600085815260208120601f198616915b8281101561360a578886015182559484019460019091019084016135eb565b508582101561362a57878501516008601f88160260020a60001904191681555b5050505050600202600101905550565b60006020828403121561364c57600080fd5b8151612e08816130d0565b6000600160a060020a038087168352808616602084015250836040830152608060608301526132616080830184612f1c565b60008154613696816134a7565b8085526020600183811680156136b357600181146136cc576136fa565b60ff1985168884015283151583028801830195506136fa565b866000528260002060005b858110156136f25781548a82018601529083019084016136d7565b890184019650505b505050505092915050565b83815260606020820152600061371e6060830185613689565b82810360408401526132618185613689565b82815260406020820152600061316f6040830184612f1c56feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220333ee6f8177146f6409ff0926887d996f1ed72eb0e938e2d13cbbe5a5033c1b464736f6c63430008110033",
- "deployedBytecode": "608060405234801561001057600080fd5b506004361061035f576000357c01000000000000000000000000000000000000000000000000000000009004806381ebdd79116101d5578063b9b3e06a11610121578063db20266f116100bf578063f2fde38b11610099578063f2fde38b1461073e578063f7502a7c14610751578063fef1b9c014610764578063ff12dcea146107a457600080fd5b8063db20266f146106f3578063e7464db11461071e578063edaab2081461073157600080fd5b8063c7109ec9116100fb578063c7109ec9146106a7578063ca5cbbb5146106ba578063cb761015146106cd578063d9322058146106e057600080fd5b8063b9b3e06a1461066e578063bfe30fb014610681578063c267ce5f1461069457600080fd5b80639301a78b1161018e5780639cd23707116101685780639cd237071461060f578063a9059cbb14610622578063b2a90a6014610635578063b967a52e1461065b57600080fd5b80639301a78b146105d257806395d89b41146105f4578063996f3a4b146105fc57600080fd5b806381ebdd791461056857806383850bcb146105885780638da5cb5b146105905780638db9877c146105a35780638ed8a9bc146105ab57806392ff0d31146105be57600080fd5b806331cef447116102af5780635c2c20051161024d5780636f3b993f116102275780636f3b993f1461052c57806370a082311461053957806376fa7a311461054c5780637da68d341461055f57600080fd5b80635c2c2005146104fd5780635c40f6f4146105065780635ccef3e71461051957600080fd5b806340eba90e1161028957806340eba90e146104c3578063428630f6146104d657806358c3b870146104de5780635b473327146104e657600080fd5b806331cef4471461049557806336f7ab5e146104a857806340615cf8146104b057600080fd5b80631935a8801161031c57806325287d42116102f657806325287d421461043c57806325d608611461044f57806327e235e3146104625780632e027abe1461048257600080fd5b80631935a88014610409578063200d2ed21461041c57806323b872dd1461042957600080fd5b806306eaa0b71461036457806306fdde03146103795780630af7eb0f146103975780630ed5a933146103c2578063153a1f3e146103df57806318160ddd146103f2575b600080fd5b610377610372366004612ed5565b6107b7565b005b610381610ab5565b60405161038e9190612f62565b60405180910390f35b6009546103aa90600160a060020a031681565b604051600160a060020a03909116815260200161038e565b6013546103cf9060ff1681565b604051901515815260200161038e565b6103cf6103ed36600461301d565b610b43565b6103fb60035481565b60405190815260200161038e565b6103776104173660046130e1565b610e06565b6007546103cf9060ff1681565b6103cf6104373660046130fe565b610e9d565b6004546103aa90600160a060020a031681565b61037761045d36600461313a565b6110bd565b6103fb610470366004613177565b60086020526000908152604090205481565b610381610490366004613192565b61111d565b6103776104a3366004612ed5565b611136565b6103816112f9565b6103776104be3660046131b5565b611306565b6103776104d13660046131df565b6113aa565b6103816116cf565b6103816116dc565b6104ee6116e9565b60405161038e93929190613236565b6103fb600f5481565b6103776105143660046130e1565b61180e565b610377610527366004612ed5565b6118a3565b600b546103cf9060ff1681565b6103fb610547366004613177565b611c5f565b61037761055a366004613177565b611c7a565b6103fb60125481565b6103fb610576366004613177565b600d6020526000908152604090205481565b610377611cf9565b6000546103aa90600160a060020a031681565b610381611d81565b6103776105b936600461313a565b611d8e565b6009546103cf9060a060020a900460ff1681565b6105e56105e0366004613177565b611dea565b60405161038e9392919061326b565b610381611e12565b61037761060a366004613293565b611e1f565b61037761061d3660046130e1565b611ed2565b6103cf6106303660046131b5565b611f51565b6009546103cf907501000000000000000000000000000000000000000000900460ff1681565b61037761066936600461313a565b612046565b6103fb61067c3660046132f6565b6120a2565b61037761068f366004613329565b6120cd565b6103776106a23660046131df565b6121d0565b6103776106b53660046130e1565b6122c7565b6103776106c8366004613391565b612384565b6103776106db36600461340a565b6124f3565b6103776106ee36600461313a565b612548565b6103fb6107013660046132f6565b600e60209081526000928352604080842090915290825290205481565b61037761072c3660046130fe565b6125a4565b6017546103cf9060ff1681565b61037761074c366004613177565b6127ac565b61037761075f366004613177565b6128c3565b61077761077236600461340a565b612942565b60408051600160a060020a039586168152949093166020850152918301521515606082015260800161038e565b6103776107b23660046130fe565b61298b565b33600160a060020a0316600c83815481106107d4576107d4613423565b6000918252602090912060049091020154600160a060020a0316148015906108075750600054600160a060020a03163314155b1561086357604080518082018252600681527f31313038303100000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b60405180910390fd5b600c828154811061087657610876613423565b6000918252602082206003600490920201015460ff16151590036108e257604080518082018252600681527f31313038303200000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b600c82815481106108f5576108f5613423565b90600052602060002090600402016002015460086000600c858154811061091e5761091e613423565b60009182526020808320600490920290910154600160a060020a0316835282019290925260400181208054909190610957908490613455565b9091555050600c80548390811061097057610970613423565b906000526020600020906004020160020154600d6000600c858154811061099957610999613423565b60009182526020808320600490920290910154600160a060020a03168352820192909252604001812080549091906109d2908490613468565b925050819055506000600c83815481106109ee576109ee613423565b906000526020600020906004020160030160006101000a81548160ff021916908315150217905550817fa0cc3a4feb26502e6e6cd57b2113d58bdab80c6711d8252356be9a49945bb5f7600c8481548110610a4b57610a4b613423565b6000918252602090912060049091020154600c8054600160a060020a039092169186908110610a7c57610a7c613423565b6000918252602090912060016004909202010154604051610aa99291600160a060020a031690869061347b565b60405180910390a25050565b60018054610ac2906134a7565b80601f0160208091040260200160405190810160405280929190818152602001828054610aee906134a7565b8015610b3b5780601f10610b1057610100808354040283529160200191610b3b565b820191906000526020600020905b815481529060010190602001808311610b1e57829003601f168201915b505050505081565b600b5460009060ff161515600103610ba357604080518082018252600681527f31313035303100000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b8151835114610bfa57604080518082018252600681527f31313035303200000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b6000805b8451811015610c4057838181518110610c1957610c19613423565b602002602001015182610c2c9190613455565b915080610c38816134e4565b915050610bfe565b5080610c4b33611c5f565b1015610c9f57604080518082018252600681527f31313035303300000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b600454600160a060020a03163314610d1a5760095460408051808201909152600681527f313130353034000000000000000000000000000000000000000000000000000060208201529060a060020a900460ff161515600114610d185760405160e560020a62461bcd02815260040161085a9190612f62565b505b606060006001935060005b8651811015610dfb57610d51878281518110610d4357610d43613423565b60200260200101513b151590565b15610d9a57610d93878281518110610d6b57610d6b613423565b6020026020010151878381518110610d8557610d85613423565b602002602001015185612ab9565b9150610dda565b610dd7878281518110610daf57610daf613423565b6020026020010151878381518110610dc957610dc9613423565b602002602001015185612c07565b91505b811515600003610de957600094505b80610df3816134e4565b915050610d25565b505050505b92915050565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a03163314610e555760405160e560020a62461bcd02815260040161085a9190612f62565b50600b805460ff19168215159081179091556040519081527fe1455bc53682229469d6919bb96d7b338cbffea93170dfb5f02242c22fb6d07f9060200160405180910390a150565b60008054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a03163314610eed5760405160e560020a62461bcd02815260040161085a9190612f62565b5081610ef885611c5f565b1015610f4c57604080518082018252600681527f31313036303100000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b6060833b1561102a57610f6883610f6287611c5f565b90612dfc565b600160a060020a038616600090815260086020526040902055610f9483610f8e86611c5f565b90612e0f565b600160a060020a038516600081815260086020526040908190209290925590517fc0ee0b8a00000000000000000000000000000000000000000000000000000000815285919063c0ee0b8a90610ff2903390889087906004016134fd565b600060405180830381600087803b15801561100c57600080fd5b505af1158015611020573d6000803e3d6000fd5b5050505050611077565b61103783610f6287611c5f565b600160a060020a03861660009081526008602052604090205561105d83610f8e86611c5f565b600160a060020a0385166000908152600860205260409020555b83600160a060020a031685600160a060020a031660008051602061374a833981519152856040516110aa91815260200190565b60405180910390a3506001949350505050565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a0316331461110c5760405160e560020a62461bcd02815260040161085a9190612f62565b5060116111198282613574565b5050565b60186020526000908152604090208054610ac2906134a7565b60095460408051808201909152600681527f31313130303100000000000000000000000000000000000000000000000000006020820152907501000000000000000000000000000000000000000000900460ff1615156001146111af5760405160e560020a62461bcd02815260040161085a9190612f62565b506009546000546040517fd3da927f000000000000000000000000000000000000000000000000000000008152336004820152600160a060020a03918216602482015291169063d3da927f90604401602060405180830381865afa15801561121b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123f919061363a565b60408051808201909152600681527f313131303032000000000000000000000000000000000000000000000000000060208201529015156001146112995760405160e560020a62461bcd02815260040161085a9190612f62565b50336000908152600a602052604090208281556002016112b98282613574565b507f3bb9553f633a7ecb4cbc5f9885e750a522496ce06deff1ed9184180ca83940c03383836040516112ed939291906134fd565b60405180910390a15050565b60058054610ac2906134a7565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146113555760405160e560020a62461bcd02815260040161085a9190612f62565b50600160a060020a0382166000818152600a6020908152604091829020600101849055815192835282018390527fa42bd6bdfcb8f9b815c68e4ce0e16dec3f1e7ac53967ee8309653de522a735b191016112ed565b600b5460ff1615806113c6575060095460a060020a900460ff16155b806113d85750816113d633611c5f565b105b1561142b57604080518082018252600681527f31313037303100000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b600054600160a060020a0384811691161461152d576009546000546040517fd3da927f000000000000000000000000000000000000000000000000000000008152600160a060020a038681166004830152918216602482015291169063d3da927f90604401602060405180830381865afa1580156114ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d1919061363a565b60408051808201909152600681527f3131303730320000000000000000000000000000000000000000000000000000602082015290151560011461152b5760405160e560020a62461bcd02815260040161085a9190612f62565b505b336000908152600860205260408120805484929061154c908490613468565b9091555050336000908152600d602052604081208054849290611570908490613455565b9091555050600c80546040805160808101825233808252600160a060020a038881166020840190815283850189815260016060860181815290880189556000989098529351600487027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c78101805492851673ffffffffffffffffffffffffffffffffffffffff1993841617905591517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c8830180549190941691161790915591517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c983015593517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8ca909101805491151560ff1990921691909117905551909182917fa256c3bc72c26fbfd6285cfde8c7e345b4d0c7ccfc725d103e9f129c5d8a039a916116c191889088908890613657565b60405180910390a250505050565b60068054610ac2906134a7565b60118054610ac2906134a7565b60148054601580549192916116fd906134a7565b80601f0160208091040260200160405190810160405280929190818152602001828054611729906134a7565b80156117765780601f1061174b57610100808354040283529160200191611776565b820191906000526020600020905b81548152906001019060200180831161175957829003601f168201915b50505050509080600201805461178b906134a7565b80601f01602080910402602001604051908101604052809291908181526020018280546117b7906134a7565b80156118045780601f106117d957610100808354040283529160200191611804565b820191906000526020600020905b8154815290600101906020018083116117e757829003601f168201915b5050505050905083565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a0316331461185d5760405160e560020a62461bcd02815260040161085a9190612f62565b506007805460ff191682151590811790915560405160ff9091161515907fe1e5c6f5867805bf3fab73f4df4b80d0e87e9262a7bc22ac7c2cb3fd5896222f90600090a250565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146118f25760405160e560020a62461bcd02815260040161085a9190612f62565b5060095460a060020a900460ff16151560000361195757604080518082018252600681527f31313039303100000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b600c828154811061196a5761196a613423565b6000918252602082206003600490920201015460ff16151590036119d657604080518082018252600681527f31313039303200000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b600c82815481106119e9576119e9613423565b90600052602060002090600402016002015460086000600c8581548110611a1257611a12613423565b6000918252602080832060016004909302019190910154600160a060020a0316835282019290925260400181208054909190611a4f908490613455565b9091555050600c805483908110611a6857611a68613423565b906000526020600020906004020160020154600d6000600c8581548110611a9157611a91613423565b60009182526020808320600490920290910154600160a060020a0316835282019290925260400181208054909190611aca908490613468565b925050819055506000600c8381548110611ae657611ae6613423565b906000526020600020906004020160030160006101000a81548160ff021916908315150217905550817f6b50d6e4941ce7ae74ed7f7f51df5fb7680754c2815a094c66bea5ca80a40eb1600c8481548110611b4357611b43613423565b6000918252602090912060049091020154600c8054600160a060020a039092169186908110611b7457611b74613423565b6000918252602090912060016004909202010154604051611ba19291600160a060020a031690869061347b565b60405180910390a2600c8281548110611bbc57611bbc613423565b6000918252602090912060016004909202010154600c8054600160a060020a039092169184908110611bf057611bf0613423565b6000918252602090912060049091020154600c8054600160a060020a039092169160008051602061374a833981519152919086908110611c3257611c32613423565b906000526020600020906004020160020154604051611c5391815260200190565b60405180910390a35050565b600160a060020a031660009081526008602052604090205490565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a03163314611cc95760405160e560020a62461bcd02815260040161085a9190612f62565b506004805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a03163314611d485760405160e560020a62461bcd02815260040161085a9190612f62565b506013805460ff191660011790556040517f8298c3671093b19970d7c94ce1f23925a962f36fec31d25075d9be072b73e10390600090a1565b60108054610ac2906134a7565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a03163314611ddd5760405160e560020a62461bcd02815260040161085a9190612f62565b5060066111198282613574565b600a602052600090815260409020805460018201546002830180549293919261178b906134a7565b60028054610ac2906134a7565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a03163314611e6e5760405160e560020a62461bcd02815260040161085a9190612f62565b5060148390556015611e808382613574565b506016611e8d8282613574565b506014546040517ff89b6034f2b759ebb2dfb08461be917a1b54f2e0523c895e7f9b5e5e14dd013e91611ec591601590601690613705565b60405180910390a1505050565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a03163314611f215760405160e560020a62461bcd02815260040161085a9190612f62565b506009805491151560a060020a0274ff000000000000000000000000000000000000000019909216919091179055565b600081611f5d33611c5f565b10156040518060400160405280600681526020017f313130343031000000000000000000000000000000000000000000000000000081525090611fb65760405160e560020a62461bcd02815260040161085a9190612f62565b5060095460408051808201909152600681527f313130343032000000000000000000000000000000000000000000000000000060208201529060a060020a900460ff16151560011461201e5760405160e560020a62461bcd02815260040161085a9190612f62565b506060833b1561203b57612033848483612ab9565b915050610e00565b612033848483612c07565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146120955760405160e560020a62461bcd02815260040161085a9190612f62565b5060056111198282613574565b600160a060020a039182166000908152600e6020908152604080832093909416825291909152205490565b816120d833866120a2565b101561212c57604080518082018252600681527f31313031303200000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b61213a82610f6233876120a2565b336000908152600e60209081526040808320600160a060020a038916845290915290205561216b82610f8e85611c5f565b600160a060020a038085166000908152600860205260409081902092909255905133918616907f7a1a1088c929a111dda2dc0ca1cc650aa78525d11fd3089abf20c8474f5d82cc906121c2908790879087906134fd565b60405180910390a350505050565b816121da33611c5f565b101561222e57604080518082018252600681527f31313030303200000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b61223b82610f6233611c5f565b3360008181526008602052604090209190915561225f908390610f8e9086906120a2565b600160a060020a0384166000818152600e602090815260408083203380855292529182902093909355519091907ecd77abc69e7bbb6de9df8cbfcca8720df3a30decf9eefd187e72ab2ea2f513906122ba9086908690613730565b60405180910390a3505050565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146123165760405160e560020a62461bcd02815260040161085a9190612f62565b506009805475ff00000000000000000000000000000000000000000019167501000000000000000000000000000000000000000000831515908102919091179091556040517fa0c691180b8089c0c84e478ee67d6325768666cd889f13de016771c6f7af1f8890600090a250565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146123d35760405160e560020a62461bcd02815260040161085a9190612f62565b50816123df86866120a2565b101561243357604080518082018252600681527f31313132303100000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b61244182610f6287876120a2565b600160a060020a038087166000908152600e602090815260408083209389168352929052205561247482610f8e85611c5f565b6008600085600160a060020a0316600160a060020a031681526020019081526020016000208190555084600160a060020a031684600160a060020a03167f7a1a1088c929a111dda2dc0ca1cc650aa78525d11fd3089abf20c8474f5d82cc8585856040516124e4939291906134fd565b60405180910390a35050505050565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146125425760405160e560020a62461bcd02815260040161085a9190612f62565b50601255565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146125975760405160e560020a62461bcd02815260040161085a9190612f62565b5060106111198282613574565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146125f35760405160e560020a62461bcd02815260040161085a9190612f62565b50600160a060020a038216156126ab578061260e83856120a2565b101561266257604080518082018252600681527f31313131303100000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b61267081610f6284866120a2565b600160a060020a038084166000908152600e60209081526040808320938816835292905220556003546126a39082612dfc565b600355612750565b600160a060020a03831660009081526008602052604090205481111561271957604080518082018252600681527f31313131303200000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b61272681610f6285611c5f565b600160a060020a03841660009081526008602052604090205560035461274c9082612dfc565b6003555b81600160a060020a031683600160a060020a031633600160a060020a03167fee02732fab40ece8284c756220846dff4b8d32058b86b35b4f0459bf172fcef08460405161279f91815260200190565b60405180910390a4505050565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146127fb5760405160e560020a62461bcd02815260040161085a9190612f62565b5060408051808201909152600681527f35303031303100000000000000000000000000000000000000000000000000006020820152600160a060020a03821661285a5760405160e560020a62461bcd02815260040161085a9190612f62565b5060008054604051600160a060020a03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146129125760405160e560020a62461bcd02815260040161085a9190612f62565b506009805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600c818154811061295257600080fd5b60009182526020909120600490910201805460018201546002830154600390930154600160a060020a0392831694509116919060ff1684565b600054604080518082019091526006815260d060020a6535303030303102602082015290600160a060020a031633146129da5760405160e560020a62461bcd02815260040161085a9190612f62565b50600160a060020a03821615612a33576129f881610f8e84866120a2565b600160a060020a038084166000908152600e6020908152604080832093881683529290522055600354612a2b9082612e0f565b600355612a6a565b612a4081610f8e85611c5f565b600160a060020a038416600090815260086020526040902055600354612a669082612e0f565b6003555b81600160a060020a031683600160a060020a031633600160a060020a03167f65adeb76912378393e600cb6f64f3310842a42e1eae86273dc775d0c47a0f2dc8460405161279f91815260200190565b60045460408051808201909152600681527f31313033303100000000000000000000000000000000000000000000000000006020820152600091600160a060020a03868116911614612b215760405160e560020a62461bcd02815260040161085a9190612f62565b50612b2f83610f6233611c5f565b33600090815260086020526040902055612b4c83610f8e86611c5f565b600160a060020a038516600081815260086020526040908190209290925590517fc0ee0b8a00000000000000000000000000000000000000000000000000000000815285919063c0ee0b8a90612baa903390889088906004016134fd565b600060405180830381600087803b158015612bc457600080fd5b505af1158015612bd8573d6000803e3d6000fd5b5050604051868152600160a060020a038816925033915060008051602061374a833981519152906020016110aa565b600454600090600160a060020a03163314801590612c2c5750600b5460ff1615156001145b15612c7f57604080518082018252600681527f31313032303100000000000000000000000000000000000000000000000000006020820152905160e560020a62461bcd02815261085a9190600401612f62565b600054600160a060020a03858116911614612d81576009546000546040517fd3da927f000000000000000000000000000000000000000000000000000000008152600160a060020a038781166004830152918216602482015291169063d3da927f90604401602060405180830381865afa158015612d01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d25919061363a565b60408051808201909152600681527f31313032303200000000000000000000000000000000000000000000000000006020820152901515600114612d7f5760405160e560020a62461bcd02815260040161085a9190612f62565b505b612d8e83610f6233611c5f565b33600090815260086020526040902055612dab83610f8e86611c5f565b600160a060020a03851660008181526008602052604090819020929092559051339060008051602061374a83398151915290612dea9087815260200190565b60405180910390a35060019392505050565b6000612e088284613468565b9392505050565b6000612e088284613455565b60e060020a634e487b7102600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612e5d57612e5d612e1b565b604052919050565b600082601f830112612e7657600080fd5b813567ffffffffffffffff811115612e9057612e90612e1b565b612ea3601f8201601f1916602001612e34565b818152846020838601011115612eb857600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215612ee857600080fd5b82359150602083013567ffffffffffffffff811115612f0657600080fd5b612f1285828601612e65565b9150509250929050565b6000815180845260005b81811015612f4257602081850181015186830182015201612f26565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000612e086020830184612f1c565b600067ffffffffffffffff821115612f8f57612f8f612e1b565b5060209081020190565b8035600160a060020a0381168114612fb057600080fd5b919050565b600082601f830112612fc657600080fd5b81356020612fdb612fd683612f75565b612e34565b82815291810284018101918181019086841115612ff757600080fd5b8286015b848110156130125780358352918301918301612ffb565b509695505050505050565b6000806040838503121561303057600080fd5b823567ffffffffffffffff8082111561304857600080fd5b818501915085601f83011261305c57600080fd5b8135602061306c612fd683612f75565b8281529181028401810191818101908984111561308857600080fd5b948201945b838610156130ad5761309e86612f99565b8252948201949082019061308d565b965050860135925050808211156130c357600080fd5b50612f1285828601612fb5565b80151581146130de57600080fd5b50565b6000602082840312156130f357600080fd5b8135612e08816130d0565b60008060006060848603121561311357600080fd5b61311c84612f99565b925061312a60208501612f99565b9150604084013590509250925092565b60006020828403121561314c57600080fd5b813567ffffffffffffffff81111561316357600080fd5b61316f84828501612e65565b949350505050565b60006020828403121561318957600080fd5b612e0882612f99565b6000602082840312156131a457600080fd5b813560ff81168114612e0857600080fd5b600080604083850312156131c857600080fd5b6131d183612f99565b946020939093013593505050565b6000806000606084860312156131f457600080fd5b6131fd84612f99565b925060208401359150604084013567ffffffffffffffff81111561322057600080fd5b61322c86828701612e65565b9150509250925092565b83815260606020820152600061324f6060830185612f1c565b82810360408401526132618185612f1c565b9695505050505050565b83815282602082015260606040820152600061328a6060830184612f1c565b95945050505050565b6000806000606084860312156132a857600080fd5b83359250602084013567ffffffffffffffff808211156132c757600080fd5b6132d387838801612e65565b935060408601359150808211156132e957600080fd5b5061322c86828701612e65565b6000806040838503121561330957600080fd5b61331283612f99565b915061332060208401612f99565b90509250929050565b6000806000806080858703121561333f57600080fd5b61334885612f99565b935061335660208601612f99565b925060408501359150606085013567ffffffffffffffff81111561337957600080fd5b61338587828801612e65565b91505092959194509250565b600080600080600060a086880312156133a957600080fd5b6133b286612f99565b94506133c060208701612f99565b93506133ce60408701612f99565b925060608601359150608086013567ffffffffffffffff8111156133f157600080fd5b6133fd88828901612e65565b9150509295509295909350565b60006020828403121561341c57600080fd5b5035919050565b60e060020a634e487b7102600052603260045260246000fd5b60e060020a634e487b7102600052601160045260246000fd5b80820180821115610e0057610e0061343c565b81810381811115610e0057610e0061343c565b6000600160a060020a0380861683528085166020840152506060604083015261328a6060830184612f1c565b6002810460018216806134bb57607f821691505b6020821081036134de5760e060020a634e487b7102600052602260045260246000fd5b50919050565b6000600182016134f6576134f661343c565b5060010190565b600160a060020a038416815282602082015260606040820152600061328a6060830184612f1c565b601f82111561356f576000818152602081206020601f8601048101602086101561354c5750805b6020601f860104820191505b8181101561356b57828155600101613558565b5050505b505050565b815167ffffffffffffffff81111561358e5761358e612e1b565b6135a28161359c84546134a7565b84613525565b602080601f8311600181146135db57600084156135bf5750858301515b60028086026008870290910a600019041982161786555061356b565b600085815260208120601f198616915b8281101561360a578886015182559484019460019091019084016135eb565b508582101561362a57878501516008601f88160260020a60001904191681555b5050505050600202600101905550565b60006020828403121561364c57600080fd5b8151612e08816130d0565b6000600160a060020a038087168352808616602084015250836040830152608060608301526132616080830184612f1c565b60008154613696816134a7565b8085526020600183811680156136b357600181146136cc576136fa565b60ff1985168884015283151583028801830195506136fa565b866000528260002060005b858110156136f25781548a82018601529083019084016136d7565b890184019650505b505050505092915050565b83815260606020820152600061371e6060830185613689565b82810360408401526132618185613689565b82815260406020820152600061316f6040830184612f1c56feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220333ee6f8177146f6409ff0926887d996f1ed72eb0e938e2d13cbbe5a5033c1b464736f6c63430008110033"
+ "bytecode": "60806040523480156200001157600080fd5b50604051620038be380380620038be8339810160408190526200003491620001d7565b600080546001600160a01b031916331790556001620000548a8262000370565b50600262000063898262000370565b50600080546001600160a01b03191633179055600f879055601281905560038690556014859055601562000098858262000370565b506016620000a7848262000370565b506010620000b6838262000370565b50506013805460ff199081169091556007805490911660011790555050600354600080546001600160a01b031681526008602052604090205550506009805460ff60a01b1916600160a01b179055506200043c92505050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200013757600080fd5b81516001600160401b03808211156200015457620001546200010f565b604051601f8301601f19908116603f011681019082821181831017156200017f576200017f6200010f565b81604052838152602092508660208588010111156200019d57600080fd5b600091505b83821015620001c15785820183015181830184015290820190620001a2565b6000602085830101528094505050505092915050565b60008060008060008060008060006101208a8c031215620001f757600080fd5b89516001600160401b03808211156200020f57600080fd5b6200021d8d838e0162000125565b9a5060208c01519150808211156200023457600080fd5b620002428d838e0162000125565b995060408c0151985060608c0151975060808c0151965060a08c01519150808211156200026e57600080fd5b6200027c8d838e0162000125565b955060c08c01519150808211156200029357600080fd5b620002a18d838e0162000125565b945060e08c0151915080821115620002b857600080fd5b50620002c78c828d0162000125565b9250506101008a015190509295985092959850929598565b600181811c90821680620002f457607f821691505b6020821081036200031557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200036b576000816000526020600020601f850160051c81016020861015620003465750805b601f850160051c820191505b81811015620003675782815560010162000352565b5050505b505050565b81516001600160401b038111156200038c576200038c6200010f565b620003a4816200039d8454620002df565b846200031b565b602080601f831160018114620003dc5760008415620003c35750858301515b600019600386901b1c1916600185901b17855562000367565b600085815260208120601f198616915b828110156200040d57888601518255948401946001909101908401620003ec565b50858210156200042c5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b613472806200044c6000396000f3fe608060405234801561001057600080fd5b50600436106103785760003560e01c806383850bcb116101d3578063c267ce5f11610104578063edaab208116100a2578063fd0e85691161007c578063fd0e85691461076b578063fd14a2221461077f578063fef1b9c014610792578063ff12dcea146107d257600080fd5b8063edaab20814610738578063f2fde38b14610745578063f7502a7c1461075857600080fd5b8063cb761015116100de578063cb761015146106d4578063d9322058146106e7578063db20266f146106fa578063e7464db11461072557600080fd5b8063c267ce5f1461069b578063c7109ec9146106ae578063ca5cbbb5146106c157600080fd5b8063996f3a4b11610171578063b2a90a601161014b578063b2a90a601461064e578063b967a52e14610662578063b9b3e06a14610675578063bfe30fb01461068857600080fd5b8063996f3a4b146106155780639cd2370714610628578063a9059cbb1461063b57600080fd5b80638ed8a9bc116101ad5780638ed8a9bc146105c457806392ff0d31146105d75780639301a78b146105eb57806395d89b411461060d57600080fd5b806383850bcb146105a15780638da5cb5b146105a95780638db9877c146105bc57600080fd5b806336f7ab5e116102ad5780635c40f6f41161024b57806370a082311161022557806370a082311461055257806376fa7a31146105655780637da68d341461057857806381ebdd791461058157600080fd5b80635c40f6f41461051f5780635ccef3e7146105325780636f3b993f1461054557600080fd5b8063428630f611610287578063428630f6146104ef57806358c3b870146104f75780635b473327146104ff5780635c2c20051461051657600080fd5b806336f7ab5e146104c157806340615cf8146104c957806340eba90e146104dc57600080fd5b8063200d2ed21161031a57806325d60861116102f457806325d608611461046857806327e235e31461047b5780632e027abe1461049b57806331cef447146104ae57600080fd5b8063200d2ed21461043557806323b872dd1461044257806325287d421461045557600080fd5b80630ed5a933116103565780630ed5a933146103db578063153a1f3e146103f857806318160ddd1461040b5780631935a8801461042257600080fd5b806306eaa0b71461037d57806306fdde03146103925780630af7eb0f146103b0575b600080fd5b61039061038b366004612bc3565b6107e5565b005b61039a610aaf565b6040516103a79190612c50565b60405180910390f35b6009546103c3906001600160a01b031681565b6040516001600160a01b0390911681526020016103a7565b6013546103e89060ff1681565b60405190151581526020016103a7565b6103e8610406366004612d12565b610b3d565b61041460035481565b6040519081526020016103a7565b610390610430366004612dd9565b610d84565b6007546103e89060ff1681565b6103e8610450366004612df6565b610e15565b6004546103c3906001600160a01b031681565b610390610476366004612e32565b610ffc565b610414610489366004612e6f565b60086020526000908152604090205481565b61039a6104a9366004612e8a565b611056565b6103906104bc366004612bc3565b61106f565b61039a6111ea565b6103906104d7366004612ead565b6111f7565b6103906104ea366004612ed7565b611295565b61039a61157c565b61039a611589565b610507611596565b6040516103a793929190612f2e565b610414600f5481565b61039061052d366004612dd9565b6116bb565b610390610540366004612bc3565b61174a565b600b546103e89060ff1681565b610414610560366004612e6f565b611acc565b610390610573366004612e6f565b611ae7565b61041460125481565b61041461058f366004612e6f565b600d6020526000908152604090205481565b610390611b53565b6000546103c3906001600160a01b031681565b61039a611bd5565b6103906105d2366004612e32565b611be2565b6009546103e890600160a81b900460ff1681565b6105fe6105f9366004612e6f565b611c38565b6040516103a793929190612f63565b61039a611c60565b610390610623366004612f8b565b611c6d565b610390610636366004612dd9565b611d1a565b6103e8610649366004612ead565b611d82565b6009546103e890600160b01b900460ff1681565b610390610670366004612e32565b611e43565b610414610683366004612fee565b611e99565b610390610696366004613021565b611ec4565b6103906106a9366004612ed7565b611fad565b6103906106bc366004612dd9565b61208a565b6103906106cf366004613089565b61211d565b6103906106e2366004613102565b61226c565b6103906106f5366004612e32565b6122bb565b610414610708366004612fee565b600e60209081526000928352604080842090915290825290205481565b610390610733366004612df6565b612311565b6017546103e89060ff1681565b610390610753366004612e6f565b6124df565b610390610766366004612e6f565b6125c9565b6009546103e890600160a01b900460ff1681565b61039061078d366004612dd9565b612635565b6107a56107a0366004613102565b61269d565b604080516001600160a01b03958616815294909316602085015291830152151560608201526080016103a7565b6103906107e0366004612df6565b6126e6565b336001600160a01b0316600c83815481106108025761080261311b565b60009182526020909120600490910201546001600160a01b03161480159061083557506000546001600160a01b03163314155b1561087757604080518082018252600681526531313038303160d01b6020820152905162461bcd60e51b815261086e9190600401612c50565b60405180910390fd5b600c828154811061088a5761088a61311b565b6000918252602082206003600490920201015460ff16151590036108dc5760408051808201825260068152651898981c181960d11b6020820152905162461bcd60e51b815261086e9190600401612c50565b600c82815481106108ef576108ef61311b565b90600052602060002090600402016002015460086000600c85815481106109185761091861311b565b600091825260208083206004909202909101546001600160a01b0316835282019290925260400181208054909190610951908490613147565b9091555050600c80548390811061096a5761096a61311b565b906000526020600020906004020160020154600d6000600c85815481106109935761099361311b565b600091825260208083206004909202909101546001600160a01b03168352820192909252604001812080549091906109cc90849061315a565b925050819055506000600c83815481106109e8576109e861311b565b906000526020600020906004020160030160006101000a81548160ff021916908315150217905550817fa0cc3a4feb26502e6e6cd57b2113d58bdab80c6711d8252356be9a49945bb5f7600c8481548110610a4557610a4561311b565b6000918252602090912060049091020154600c80546001600160a01b039092169186908110610a7657610a7661311b565b6000918252602090912060016004909202010154604051610aa392916001600160a01b031690869061316d565b60405180910390a25050565b60018054610abc90613199565b80601f0160208091040260200160405190810160405280929190818152602001828054610ae890613199565b8015610b355780601f10610b0a57610100808354040283529160200191610b35565b820191906000526020600020905b815481529060010190602001808311610b1857829003601f168201915b505050505081565b600b5460009060ff161515600103610b8357604080518082018252600681526531313035303160d01b6020820152905162461bcd60e51b815261086e9190600401612c50565b8151835114610bc05760408051808201825260068152651898981a981960d11b6020820152905162461bcd60e51b815261086e9190600401612c50565b6000805b8451811015610bfc57838181518110610bdf57610bdf61311b565b602002602001015182610bf29190613147565b9150600101610bc4565b5080610c0733611acc565b1015610c4157604080518082018252600681526531313035303360d01b6020820152905162461bcd60e51b815261086e9190600401612c50565b6004546001600160a01b03163314610ca2576009546040805180820190915260068152650c4c4c0d4c0d60d21b602082015290600160a81b900460ff161515600114610ca05760405162461bcd60e51b815260040161086e9190612c50565b505b606060006001935060005b8651811015610d7957610cd9878281518110610ccb57610ccb61311b565b60200260200101513b151590565b15610d2257610d1b878281518110610cf357610cf361311b565b6020026020010151878381518110610d0d57610d0d61311b565b60200260200101518561280e565b9150610d62565b610d5f878281518110610d3757610d3761311b565b6020026020010151878381518110610d5157610d5161311b565b602002602001015185612929565b91505b811515600003610d7157600094505b600101610cad565b505050505b92915050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314610dcd5760405162461bcd60e51b815260040161086e9190612c50565b50600b805460ff19168215159081179091556040519081527fe1455bc53682229469d6919bb96d7b338cbffea93170dfb5f02242c22fb6d07f9060200160405180910390a150565b6000805460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314610e5f5760405162461bcd60e51b815260040161086e9190612c50565b5081610e6a85611acc565b1015610ea457604080518082018252600681526531313036303160d01b6020820152905162461bcd60e51b815261086e9190600401612c50565b6060833b15610f6957610ec083610eba87611acc565b90612aed565b6001600160a01b038616600090815260086020526040902055610eec83610ee686611acc565b90612b00565b6001600160a01b0385166000818152600860205260409081902092909255905163607705c560e11b815285919063c0ee0b8a90610f31903390889087906004016131d3565b600060405180830381600087803b158015610f4b57600080fd5b505af1158015610f5f573d6000803e3d6000fd5b5050505050610fb6565b610f7683610eba87611acc565b6001600160a01b038616600090815260086020526040902055610f9c83610ee686611acc565b6001600160a01b0385166000908152600860205260409020555b836001600160a01b0316856001600160a01b031660008051602061341d83398151915285604051610fe991815260200190565b60405180910390a3506001949350505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146110455760405162461bcd60e51b815260040161086e9190612c50565b506011611052828261324b565b5050565b60186020526000908152604090208054610abc90613199565b60095460408051808201909152600681526531313130303160d01b602082015290600160b01b900460ff1615156001146110bc5760405162461bcd60e51b815260040161086e9190612c50565b50600954600160a01b900460ff16151560010361118b5760095460005460405163d3da927f60e01b81523360048201526001600160a01b03918216602482015291169063d3da927f90604401602060405180830381865afa158015611125573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611149919061330b565b60408051808201909152600681526518989898181960d11b60208201529015156001146111895760405162461bcd60e51b815260040161086e9190612c50565b505b336000908152600a602052604090208281556002016111aa828261324b565b507f3bb9553f633a7ecb4cbc5f9885e750a522496ce06deff1ed9184180ca83940c03383836040516111de939291906131d3565b60405180910390a15050565b60058054610abc90613199565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146112405760405162461bcd60e51b815260040161086e9190612c50565b506001600160a01b0382166000818152600a6020908152604091829020600101849055815192835282018390527fa42bd6bdfcb8f9b815c68e4ce0e16dec3f1e7ac53967ee8309653de522a735b191016111de565b600b5460ff1615806112b15750600954600160a81b900460ff16155b806112c35750816112c133611acc565b105b156112fc57604080518082018252600681526531313037303160d01b6020820152905162461bcd60e51b815261086e9190600401612c50565b6000546001600160a01b038481169116148015906113285750600954600160a01b900460ff1615156001145b156113e75760095460005460405163d3da927f60e01b81526001600160a01b038681166004830152918216602482015291169063d3da927f90604401602060405180830381865afa158015611381573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a5919061330b565b6040805180820190915260068152651898981b981960d11b60208201529015156001146113e55760405162461bcd60e51b815260040161086e9190612c50565b505b336000908152600860205260408120805484929061140690849061315a565b9091555050336000908152600d60205260408120805484929061142a908490613147565b9091555050600c805460408051608081018252338082526001600160a01b038881166020840190815283850189815260016060860181815290880189556000989098529351600487027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7810180549285166001600160a01b031993841617905591517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c8830180549190941691161790915591517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c983015593517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8ca909101805491151560ff1990921691909117905551909182917fa256c3bc72c26fbfd6285cfde8c7e345b4d0c7ccfc725d103e9f129c5d8a039a9161156e91889088908890613328565b60405180910390a250505050565b60068054610abc90613199565b60118054610abc90613199565b60148054601580549192916115aa90613199565b80601f01602080910402602001604051908101604052809291908181526020018280546115d690613199565b80156116235780601f106115f857610100808354040283529160200191611623565b820191906000526020600020905b81548152906001019060200180831161160657829003601f168201915b50505050509080600201805461163890613199565b80601f016020809104026020016040519081016040528092919081815260200182805461166490613199565b80156116b15780601f10611686576101008083540402835291602001916116b1565b820191906000526020600020905b81548152906001019060200180831161169457829003601f168201915b5050505050905083565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146117045760405162461bcd60e51b815260040161086e9190612c50565b506007805460ff191682151590811790915560405160ff9091161515907fe1e5c6f5867805bf3fab73f4df4b80d0e87e9262a7bc22ac7c2cb3fd5896222f90600090a250565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146117935760405162461bcd60e51b815260040161086e9190612c50565b50600954600160a81b900460ff1615156000036117de57604080518082018252600681526531313039303160d01b6020820152905162461bcd60e51b815261086e9190600401612c50565b600c82815481106117f1576117f161311b565b6000918252602082206003600490920201015460ff16151590036118435760408051808201825260068152651898981c981960d11b6020820152905162461bcd60e51b815261086e9190600401612c50565b600c82815481106118565761185661311b565b90600052602060002090600402016002015460086000600c858154811061187f5761187f61311b565b60009182526020808320600160049093020191909101546001600160a01b03168352820192909252604001812080549091906118bc908490613147565b9091555050600c8054839081106118d5576118d561311b565b906000526020600020906004020160020154600d6000600c85815481106118fe576118fe61311b565b600091825260208083206004909202909101546001600160a01b031683528201929092526040018120805490919061193790849061315a565b925050819055506000600c83815481106119535761195361311b565b906000526020600020906004020160030160006101000a81548160ff021916908315150217905550817f6b50d6e4941ce7ae74ed7f7f51df5fb7680754c2815a094c66bea5ca80a40eb1600c84815481106119b0576119b061311b565b6000918252602090912060049091020154600c80546001600160a01b0390921691869081106119e1576119e161311b565b6000918252602090912060016004909202010154604051611a0e92916001600160a01b031690869061316d565b60405180910390a2600c8281548110611a2957611a2961311b565b6000918252602090912060016004909202010154600c80546001600160a01b039092169184908110611a5d57611a5d61311b565b6000918252602090912060049091020154600c80546001600160a01b039092169160008051602061341d833981519152919086908110611a9f57611a9f61311b565b906000526020600020906004020160020154604051611ac091815260200190565b60405180910390a35050565b6001600160a01b031660009081526008602052604090205490565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611b305760405162461bcd60e51b815260040161086e9190612c50565b50600480546001600160a01b0319166001600160a01b0392909216919091179055565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611b9c5760405162461bcd60e51b815260040161086e9190612c50565b506013805460ff191660011790556040517f8298c3671093b19970d7c94ce1f23925a962f36fec31d25075d9be072b73e10390600090a1565b60108054610abc90613199565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611c2b5760405162461bcd60e51b815260040161086e9190612c50565b506006611052828261324b565b600a602052600090815260409020805460018201546002830180549293919261163890613199565b60028054610abc90613199565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611cb65760405162461bcd60e51b815260040161086e9190612c50565b5060148390556015611cc8838261324b565b506016611cd5828261324b565b506014546040517ff89b6034f2b759ebb2dfb08461be917a1b54f2e0523c895e7f9b5e5e14dd013e91611d0d916015906016906133d8565b60405180910390a1505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611d635760405162461bcd60e51b815260040161086e9190612c50565b5060098054911515600160a81b0260ff60a81b19909216919091179055565b600081611d8e33611acc565b10156040518060400160405280600681526020016531313034303160d01b81525090611dcd5760405162461bcd60e51b815260040161086e9190612c50565b506009546040805180820190915260068152651898981a181960d11b602082015290600160a81b900460ff161515600114611e1b5760405162461bcd60e51b815260040161086e9190612c50565b506060833b15611e3857611e3084848361280e565b915050610d7e565b611e30848483612929565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611e8c5760405162461bcd60e51b815260040161086e9190612c50565b506005611052828261324b565b6001600160a01b039182166000908152600e6020908152604080832093909416825291909152205490565b81611ecf3386611e99565b1015611f0957604080518082018252600681526518989818981960d11b6020820152905162461bcd60e51b815261086e9190600401612c50565b611f1782610eba3387611e99565b336000908152600e602090815260408083206001600160a01b0389168452909152902055611f4882610ee685611acc565b6001600160a01b038085166000908152600860205260409081902092909255905133918616907f7a1a1088c929a111dda2dc0ca1cc650aa78525d11fd3089abf20c8474f5d82cc90611f9f908790879087906131d3565b60405180910390a350505050565b81611fb733611acc565b1015611ff157604080518082018252600681526518989818181960d11b6020820152905162461bcd60e51b815261086e9190600401612c50565b611ffe82610eba33611acc565b33600081815260086020526040902091909155612022908390610ee6908690611e99565b6001600160a01b0384166000818152600e602090815260408083203380855292529182902093909355519091907ecd77abc69e7bbb6de9df8cbfcca8720df3a30decf9eefd187e72ab2ea2f5139061207d9086908690613403565b60405180910390a3505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146120d35760405162461bcd60e51b815260040161086e9190612c50565b506009805460ff60b01b1916600160b01b831515908102919091179091556040517fa0c691180b8089c0c84e478ee67d6325768666cd889f13de016771c6f7af1f8890600090a250565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146121665760405162461bcd60e51b815260040161086e9190612c50565b50816121728686611e99565b10156121ac57604080518082018252600681526531313132303160d01b6020820152905162461bcd60e51b815261086e9190600401612c50565b6121ba82610eba8787611e99565b6001600160a01b038087166000908152600e60209081526040808320938916835292905220556121ed82610ee685611acc565b60086000856001600160a01b03166001600160a01b0316815260200190815260200160002081905550846001600160a01b0316846001600160a01b03167f7a1a1088c929a111dda2dc0ca1cc650aa78525d11fd3089abf20c8474f5d82cc85858560405161225d939291906131d3565b60405180910390a35050505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146122b55760405162461bcd60e51b815260040161086e9190612c50565b50601255565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146123045760405162461bcd60e51b815260040161086e9190612c50565b506010611052828261324b565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461235a5760405162461bcd60e51b815260040161086e9190612c50565b506001600160a01b038216156123f857806123758385611e99565b10156123af57604080518082018252600681526531313131303160d01b6020820152905162461bcd60e51b815261086e9190600401612c50565b6123bd81610eba8486611e99565b6001600160a01b038084166000908152600e60209081526040808320938816835292905220556003546123f09082612aed565b600355612483565b6001600160a01b03831660009081526008602052604090205481111561244c57604080518082018252600681526518989898981960d11b6020820152905162461bcd60e51b815261086e9190600401612c50565b61245981610eba85611acc565b6001600160a01b03841660009081526008602052604090205560035461247f9082612aed565b6003555b816001600160a01b0316836001600160a01b0316336001600160a01b03167fee02732fab40ece8284c756220846dff4b8d32058b86b35b4f0459bf172fcef0846040516124d291815260200190565b60405180910390a4505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146125285760405162461bcd60e51b815260040161086e9190612c50565b5060408051808201909152600681526535303031303160d01b60208201526001600160a01b03821661256d5760405162461bcd60e51b815260040161086e9190612c50565b50600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146126125760405162461bcd60e51b815260040161086e9190612c50565b50600980546001600160a01b0319166001600160a01b0392909216919091179055565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461267e5760405162461bcd60e51b815260040161086e9190612c50565b5060098054911515600160a01b0260ff60a01b19909216919091179055565b600c81815481106126ad57600080fd5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509116919060ff1684565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461272f5760405162461bcd60e51b815260040161086e9190612c50565b506001600160a01b038216156127885761274d81610ee68486611e99565b6001600160a01b038084166000908152600e60209081526040808320938816835292905220556003546127809082612b00565b6003556127bf565b61279581610ee685611acc565b6001600160a01b0384166000908152600860205260409020556003546127bb9082612b00565b6003555b816001600160a01b0316836001600160a01b0316336001600160a01b03167f65adeb76912378393e600cb6f64f3310842a42e1eae86273dc775d0c47a0f2dc846040516124d291815260200190565b60045460408051808201909152600681526531313033303160d01b60208201526000916001600160a01b0386811691161461285c5760405162461bcd60e51b815260040161086e9190612c50565b5061286a83610eba33611acc565b3360009081526008602052604090205561288783610ee686611acc565b6001600160a01b0385166000818152600860205260409081902092909255905163607705c560e11b815285919063c0ee0b8a906128cc903390889088906004016131d3565b600060405180830381600087803b1580156128e657600080fd5b505af11580156128fa573d6000803e3d6000fd5b50506040518681526001600160a01b038816925033915060008051602061341d83398151915290602001610fe9565b6004546000906001600160a01b0316331480159061294e5750600b5460ff1615156001145b1561298757604080518082018252600681526531313032303160d01b6020820152905162461bcd60e51b815261086e9190600401612c50565b6000546001600160a01b038581169116148015906129b35750600954600160a01b900460ff1615156001145b15612a725760095460005460405163d3da927f60e01b81526001600160a01b038781166004830152918216602482015291169063d3da927f90604401602060405180830381865afa158015612a0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a30919061330b565b60408051808201909152600681526518989819181960d11b6020820152901515600114612a705760405162461bcd60e51b815260040161086e9190612c50565b505b612a7f83610eba33611acc565b33600090815260086020526040902055612a9c83610ee686611acc565b6001600160a01b03851660008181526008602052604090819020929092559051339060008051602061341d83398151915290612adb9087815260200190565b60405180910390a35060019392505050565b6000612af9828461315a565b9392505050565b6000612af98284613147565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612b4b57612b4b612b0c565b604052919050565b600082601f830112612b6457600080fd5b813567ffffffffffffffff811115612b7e57612b7e612b0c565b612b91601f8201601f1916602001612b22565b818152846020838601011115612ba657600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215612bd657600080fd5b82359150602083013567ffffffffffffffff811115612bf457600080fd5b612c0085828601612b53565b9150509250929050565b6000815180845260005b81811015612c3057602081850181015186830182015201612c14565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000612af96020830184612c0a565b600067ffffffffffffffff821115612c7d57612c7d612b0c565b5060051b60200190565b80356001600160a01b0381168114612c9e57600080fd5b919050565b600082601f830112612cb457600080fd5b81356020612cc9612cc483612c63565b612b22565b8083825260208201915060208460051b870101935086841115612ceb57600080fd5b602086015b84811015612d075780358352918301918301612cf0565b509695505050505050565b60008060408385031215612d2557600080fd5b823567ffffffffffffffff80821115612d3d57600080fd5b818501915085601f830112612d5157600080fd5b81356020612d61612cc483612c63565b82815260059290921b84018101918181019089841115612d8057600080fd5b948201945b83861015612da557612d9686612c87565b82529482019490820190612d85565b96505086013592505080821115612dbb57600080fd5b50612c0085828601612ca3565b8015158114612dd657600080fd5b50565b600060208284031215612deb57600080fd5b8135612af981612dc8565b600080600060608486031215612e0b57600080fd5b612e1484612c87565b9250612e2260208501612c87565b9150604084013590509250925092565b600060208284031215612e4457600080fd5b813567ffffffffffffffff811115612e5b57600080fd5b612e6784828501612b53565b949350505050565b600060208284031215612e8157600080fd5b612af982612c87565b600060208284031215612e9c57600080fd5b813560ff81168114612af957600080fd5b60008060408385031215612ec057600080fd5b612ec983612c87565b946020939093013593505050565b600080600060608486031215612eec57600080fd5b612ef584612c87565b925060208401359150604084013567ffffffffffffffff811115612f1857600080fd5b612f2486828701612b53565b9150509250925092565b838152606060208201526000612f476060830185612c0a565b8281036040840152612f598185612c0a565b9695505050505050565b838152826020820152606060408201526000612f826060830184612c0a565b95945050505050565b600080600060608486031215612fa057600080fd5b83359250602084013567ffffffffffffffff80821115612fbf57600080fd5b612fcb87838801612b53565b93506040860135915080821115612fe157600080fd5b50612f2486828701612b53565b6000806040838503121561300157600080fd5b61300a83612c87565b915061301860208401612c87565b90509250929050565b6000806000806080858703121561303757600080fd5b61304085612c87565b935061304e60208601612c87565b925060408501359150606085013567ffffffffffffffff81111561307157600080fd5b61307d87828801612b53565b91505092959194509250565b600080600080600060a086880312156130a157600080fd5b6130aa86612c87565b94506130b860208701612c87565b93506130c660408701612c87565b925060608601359150608086013567ffffffffffffffff8111156130e957600080fd5b6130f588828901612b53565b9150509295509295909350565b60006020828403121561311457600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610d7e57610d7e613131565b81810381811115610d7e57610d7e613131565b6001600160a01b03848116825283166020820152606060408201819052600090612f8290830184612c0a565b600181811c908216806131ad57607f821691505b6020821081036131cd57634e487b7160e01b600052602260045260246000fd5b50919050565b60018060a01b0384168152826020820152606060408201526000612f826060830184612c0a565b601f821115613246576000816000526020600020601f850160051c810160208610156132235750805b601f850160051c820191505b818110156132425782815560010161322f565b5050505b505050565b815167ffffffffffffffff81111561326557613265612b0c565b613279816132738454613199565b846131fa565b602080601f8311600181146132ae57600084156132965750858301515b600019600386901b1c1916600185901b178555613242565b600085815260208120601f198616915b828110156132dd578886015182559484019460019091019084016132be565b50858210156132fb5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006020828403121561331d57600080fd5b8151612af981612dc8565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612f5990830184612c0a565b6000815461336881613199565b808552602060018381168015613385576001811461339f576133cd565b60ff1985168884015283151560051b8801830195506133cd565b866000528260002060005b858110156133c55781548a82018601529083019084016133aa565b890184019650505b505050505092915050565b8381526060602082015260006133f1606083018561335b565b8281036040840152612f59818561335b565b828152604060208201526000612e676040830184612c0a56feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212201889db3f768c3826c5ce92020d70f772bf2f23adad1ce1774ab7ed5a27c863ee64736f6c63430008170033",
+ "deployedBytecode": "608060405234801561001057600080fd5b50600436106103785760003560e01c806383850bcb116101d3578063c267ce5f11610104578063edaab208116100a2578063fd0e85691161007c578063fd0e85691461076b578063fd14a2221461077f578063fef1b9c014610792578063ff12dcea146107d257600080fd5b8063edaab20814610738578063f2fde38b14610745578063f7502a7c1461075857600080fd5b8063cb761015116100de578063cb761015146106d4578063d9322058146106e7578063db20266f146106fa578063e7464db11461072557600080fd5b8063c267ce5f1461069b578063c7109ec9146106ae578063ca5cbbb5146106c157600080fd5b8063996f3a4b11610171578063b2a90a601161014b578063b2a90a601461064e578063b967a52e14610662578063b9b3e06a14610675578063bfe30fb01461068857600080fd5b8063996f3a4b146106155780639cd2370714610628578063a9059cbb1461063b57600080fd5b80638ed8a9bc116101ad5780638ed8a9bc146105c457806392ff0d31146105d75780639301a78b146105eb57806395d89b411461060d57600080fd5b806383850bcb146105a15780638da5cb5b146105a95780638db9877c146105bc57600080fd5b806336f7ab5e116102ad5780635c40f6f41161024b57806370a082311161022557806370a082311461055257806376fa7a31146105655780637da68d341461057857806381ebdd791461058157600080fd5b80635c40f6f41461051f5780635ccef3e7146105325780636f3b993f1461054557600080fd5b8063428630f611610287578063428630f6146104ef57806358c3b870146104f75780635b473327146104ff5780635c2c20051461051657600080fd5b806336f7ab5e146104c157806340615cf8146104c957806340eba90e146104dc57600080fd5b8063200d2ed21161031a57806325d60861116102f457806325d608611461046857806327e235e31461047b5780632e027abe1461049b57806331cef447146104ae57600080fd5b8063200d2ed21461043557806323b872dd1461044257806325287d421461045557600080fd5b80630ed5a933116103565780630ed5a933146103db578063153a1f3e146103f857806318160ddd1461040b5780631935a8801461042257600080fd5b806306eaa0b71461037d57806306fdde03146103925780630af7eb0f146103b0575b600080fd5b61039061038b366004612bc3565b6107e5565b005b61039a610aaf565b6040516103a79190612c50565b60405180910390f35b6009546103c3906001600160a01b031681565b6040516001600160a01b0390911681526020016103a7565b6013546103e89060ff1681565b60405190151581526020016103a7565b6103e8610406366004612d12565b610b3d565b61041460035481565b6040519081526020016103a7565b610390610430366004612dd9565b610d84565b6007546103e89060ff1681565b6103e8610450366004612df6565b610e15565b6004546103c3906001600160a01b031681565b610390610476366004612e32565b610ffc565b610414610489366004612e6f565b60086020526000908152604090205481565b61039a6104a9366004612e8a565b611056565b6103906104bc366004612bc3565b61106f565b61039a6111ea565b6103906104d7366004612ead565b6111f7565b6103906104ea366004612ed7565b611295565b61039a61157c565b61039a611589565b610507611596565b6040516103a793929190612f2e565b610414600f5481565b61039061052d366004612dd9565b6116bb565b610390610540366004612bc3565b61174a565b600b546103e89060ff1681565b610414610560366004612e6f565b611acc565b610390610573366004612e6f565b611ae7565b61041460125481565b61041461058f366004612e6f565b600d6020526000908152604090205481565b610390611b53565b6000546103c3906001600160a01b031681565b61039a611bd5565b6103906105d2366004612e32565b611be2565b6009546103e890600160a81b900460ff1681565b6105fe6105f9366004612e6f565b611c38565b6040516103a793929190612f63565b61039a611c60565b610390610623366004612f8b565b611c6d565b610390610636366004612dd9565b611d1a565b6103e8610649366004612ead565b611d82565b6009546103e890600160b01b900460ff1681565b610390610670366004612e32565b611e43565b610414610683366004612fee565b611e99565b610390610696366004613021565b611ec4565b6103906106a9366004612ed7565b611fad565b6103906106bc366004612dd9565b61208a565b6103906106cf366004613089565b61211d565b6103906106e2366004613102565b61226c565b6103906106f5366004612e32565b6122bb565b610414610708366004612fee565b600e60209081526000928352604080842090915290825290205481565b610390610733366004612df6565b612311565b6017546103e89060ff1681565b610390610753366004612e6f565b6124df565b610390610766366004612e6f565b6125c9565b6009546103e890600160a01b900460ff1681565b61039061078d366004612dd9565b612635565b6107a56107a0366004613102565b61269d565b604080516001600160a01b03958616815294909316602085015291830152151560608201526080016103a7565b6103906107e0366004612df6565b6126e6565b336001600160a01b0316600c83815481106108025761080261311b565b60009182526020909120600490910201546001600160a01b03161480159061083557506000546001600160a01b03163314155b1561087757604080518082018252600681526531313038303160d01b6020820152905162461bcd60e51b815261086e9190600401612c50565b60405180910390fd5b600c828154811061088a5761088a61311b565b6000918252602082206003600490920201015460ff16151590036108dc5760408051808201825260068152651898981c181960d11b6020820152905162461bcd60e51b815261086e9190600401612c50565b600c82815481106108ef576108ef61311b565b90600052602060002090600402016002015460086000600c85815481106109185761091861311b565b600091825260208083206004909202909101546001600160a01b0316835282019290925260400181208054909190610951908490613147565b9091555050600c80548390811061096a5761096a61311b565b906000526020600020906004020160020154600d6000600c85815481106109935761099361311b565b600091825260208083206004909202909101546001600160a01b03168352820192909252604001812080549091906109cc90849061315a565b925050819055506000600c83815481106109e8576109e861311b565b906000526020600020906004020160030160006101000a81548160ff021916908315150217905550817fa0cc3a4feb26502e6e6cd57b2113d58bdab80c6711d8252356be9a49945bb5f7600c8481548110610a4557610a4561311b565b6000918252602090912060049091020154600c80546001600160a01b039092169186908110610a7657610a7661311b565b6000918252602090912060016004909202010154604051610aa392916001600160a01b031690869061316d565b60405180910390a25050565b60018054610abc90613199565b80601f0160208091040260200160405190810160405280929190818152602001828054610ae890613199565b8015610b355780601f10610b0a57610100808354040283529160200191610b35565b820191906000526020600020905b815481529060010190602001808311610b1857829003601f168201915b505050505081565b600b5460009060ff161515600103610b8357604080518082018252600681526531313035303160d01b6020820152905162461bcd60e51b815261086e9190600401612c50565b8151835114610bc05760408051808201825260068152651898981a981960d11b6020820152905162461bcd60e51b815261086e9190600401612c50565b6000805b8451811015610bfc57838181518110610bdf57610bdf61311b565b602002602001015182610bf29190613147565b9150600101610bc4565b5080610c0733611acc565b1015610c4157604080518082018252600681526531313035303360d01b6020820152905162461bcd60e51b815261086e9190600401612c50565b6004546001600160a01b03163314610ca2576009546040805180820190915260068152650c4c4c0d4c0d60d21b602082015290600160a81b900460ff161515600114610ca05760405162461bcd60e51b815260040161086e9190612c50565b505b606060006001935060005b8651811015610d7957610cd9878281518110610ccb57610ccb61311b565b60200260200101513b151590565b15610d2257610d1b878281518110610cf357610cf361311b565b6020026020010151878381518110610d0d57610d0d61311b565b60200260200101518561280e565b9150610d62565b610d5f878281518110610d3757610d3761311b565b6020026020010151878381518110610d5157610d5161311b565b602002602001015185612929565b91505b811515600003610d7157600094505b600101610cad565b505050505b92915050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314610dcd5760405162461bcd60e51b815260040161086e9190612c50565b50600b805460ff19168215159081179091556040519081527fe1455bc53682229469d6919bb96d7b338cbffea93170dfb5f02242c22fb6d07f9060200160405180910390a150565b6000805460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314610e5f5760405162461bcd60e51b815260040161086e9190612c50565b5081610e6a85611acc565b1015610ea457604080518082018252600681526531313036303160d01b6020820152905162461bcd60e51b815261086e9190600401612c50565b6060833b15610f6957610ec083610eba87611acc565b90612aed565b6001600160a01b038616600090815260086020526040902055610eec83610ee686611acc565b90612b00565b6001600160a01b0385166000818152600860205260409081902092909255905163607705c560e11b815285919063c0ee0b8a90610f31903390889087906004016131d3565b600060405180830381600087803b158015610f4b57600080fd5b505af1158015610f5f573d6000803e3d6000fd5b5050505050610fb6565b610f7683610eba87611acc565b6001600160a01b038616600090815260086020526040902055610f9c83610ee686611acc565b6001600160a01b0385166000908152600860205260409020555b836001600160a01b0316856001600160a01b031660008051602061341d83398151915285604051610fe991815260200190565b60405180910390a3506001949350505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146110455760405162461bcd60e51b815260040161086e9190612c50565b506011611052828261324b565b5050565b60186020526000908152604090208054610abc90613199565b60095460408051808201909152600681526531313130303160d01b602082015290600160b01b900460ff1615156001146110bc5760405162461bcd60e51b815260040161086e9190612c50565b50600954600160a01b900460ff16151560010361118b5760095460005460405163d3da927f60e01b81523360048201526001600160a01b03918216602482015291169063d3da927f90604401602060405180830381865afa158015611125573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611149919061330b565b60408051808201909152600681526518989898181960d11b60208201529015156001146111895760405162461bcd60e51b815260040161086e9190612c50565b505b336000908152600a602052604090208281556002016111aa828261324b565b507f3bb9553f633a7ecb4cbc5f9885e750a522496ce06deff1ed9184180ca83940c03383836040516111de939291906131d3565b60405180910390a15050565b60058054610abc90613199565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146112405760405162461bcd60e51b815260040161086e9190612c50565b506001600160a01b0382166000818152600a6020908152604091829020600101849055815192835282018390527fa42bd6bdfcb8f9b815c68e4ce0e16dec3f1e7ac53967ee8309653de522a735b191016111de565b600b5460ff1615806112b15750600954600160a81b900460ff16155b806112c35750816112c133611acc565b105b156112fc57604080518082018252600681526531313037303160d01b6020820152905162461bcd60e51b815261086e9190600401612c50565b6000546001600160a01b038481169116148015906113285750600954600160a01b900460ff1615156001145b156113e75760095460005460405163d3da927f60e01b81526001600160a01b038681166004830152918216602482015291169063d3da927f90604401602060405180830381865afa158015611381573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a5919061330b565b6040805180820190915260068152651898981b981960d11b60208201529015156001146113e55760405162461bcd60e51b815260040161086e9190612c50565b505b336000908152600860205260408120805484929061140690849061315a565b9091555050336000908152600d60205260408120805484929061142a908490613147565b9091555050600c805460408051608081018252338082526001600160a01b038881166020840190815283850189815260016060860181815290880189556000989098529351600487027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7810180549285166001600160a01b031993841617905591517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c8830180549190941691161790915591517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c983015593517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8ca909101805491151560ff1990921691909117905551909182917fa256c3bc72c26fbfd6285cfde8c7e345b4d0c7ccfc725d103e9f129c5d8a039a9161156e91889088908890613328565b60405180910390a250505050565b60068054610abc90613199565b60118054610abc90613199565b60148054601580549192916115aa90613199565b80601f01602080910402602001604051908101604052809291908181526020018280546115d690613199565b80156116235780601f106115f857610100808354040283529160200191611623565b820191906000526020600020905b81548152906001019060200180831161160657829003601f168201915b50505050509080600201805461163890613199565b80601f016020809104026020016040519081016040528092919081815260200182805461166490613199565b80156116b15780601f10611686576101008083540402835291602001916116b1565b820191906000526020600020905b81548152906001019060200180831161169457829003601f168201915b5050505050905083565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146117045760405162461bcd60e51b815260040161086e9190612c50565b506007805460ff191682151590811790915560405160ff9091161515907fe1e5c6f5867805bf3fab73f4df4b80d0e87e9262a7bc22ac7c2cb3fd5896222f90600090a250565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146117935760405162461bcd60e51b815260040161086e9190612c50565b50600954600160a81b900460ff1615156000036117de57604080518082018252600681526531313039303160d01b6020820152905162461bcd60e51b815261086e9190600401612c50565b600c82815481106117f1576117f161311b565b6000918252602082206003600490920201015460ff16151590036118435760408051808201825260068152651898981c981960d11b6020820152905162461bcd60e51b815261086e9190600401612c50565b600c82815481106118565761185661311b565b90600052602060002090600402016002015460086000600c858154811061187f5761187f61311b565b60009182526020808320600160049093020191909101546001600160a01b03168352820192909252604001812080549091906118bc908490613147565b9091555050600c8054839081106118d5576118d561311b565b906000526020600020906004020160020154600d6000600c85815481106118fe576118fe61311b565b600091825260208083206004909202909101546001600160a01b031683528201929092526040018120805490919061193790849061315a565b925050819055506000600c83815481106119535761195361311b565b906000526020600020906004020160030160006101000a81548160ff021916908315150217905550817f6b50d6e4941ce7ae74ed7f7f51df5fb7680754c2815a094c66bea5ca80a40eb1600c84815481106119b0576119b061311b565b6000918252602090912060049091020154600c80546001600160a01b0390921691869081106119e1576119e161311b565b6000918252602090912060016004909202010154604051611a0e92916001600160a01b031690869061316d565b60405180910390a2600c8281548110611a2957611a2961311b565b6000918252602090912060016004909202010154600c80546001600160a01b039092169184908110611a5d57611a5d61311b565b6000918252602090912060049091020154600c80546001600160a01b039092169160008051602061341d833981519152919086908110611a9f57611a9f61311b565b906000526020600020906004020160020154604051611ac091815260200190565b60405180910390a35050565b6001600160a01b031660009081526008602052604090205490565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611b305760405162461bcd60e51b815260040161086e9190612c50565b50600480546001600160a01b0319166001600160a01b0392909216919091179055565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611b9c5760405162461bcd60e51b815260040161086e9190612c50565b506013805460ff191660011790556040517f8298c3671093b19970d7c94ce1f23925a962f36fec31d25075d9be072b73e10390600090a1565b60108054610abc90613199565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611c2b5760405162461bcd60e51b815260040161086e9190612c50565b506006611052828261324b565b600a602052600090815260409020805460018201546002830180549293919261163890613199565b60028054610abc90613199565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611cb65760405162461bcd60e51b815260040161086e9190612c50565b5060148390556015611cc8838261324b565b506016611cd5828261324b565b506014546040517ff89b6034f2b759ebb2dfb08461be917a1b54f2e0523c895e7f9b5e5e14dd013e91611d0d916015906016906133d8565b60405180910390a1505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611d635760405162461bcd60e51b815260040161086e9190612c50565b5060098054911515600160a81b0260ff60a81b19909216919091179055565b600081611d8e33611acc565b10156040518060400160405280600681526020016531313034303160d01b81525090611dcd5760405162461bcd60e51b815260040161086e9190612c50565b506009546040805180820190915260068152651898981a181960d11b602082015290600160a81b900460ff161515600114611e1b5760405162461bcd60e51b815260040161086e9190612c50565b506060833b15611e3857611e3084848361280e565b915050610d7e565b611e30848483612929565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611e8c5760405162461bcd60e51b815260040161086e9190612c50565b506005611052828261324b565b6001600160a01b039182166000908152600e6020908152604080832093909416825291909152205490565b81611ecf3386611e99565b1015611f0957604080518082018252600681526518989818981960d11b6020820152905162461bcd60e51b815261086e9190600401612c50565b611f1782610eba3387611e99565b336000908152600e602090815260408083206001600160a01b0389168452909152902055611f4882610ee685611acc565b6001600160a01b038085166000908152600860205260409081902092909255905133918616907f7a1a1088c929a111dda2dc0ca1cc650aa78525d11fd3089abf20c8474f5d82cc90611f9f908790879087906131d3565b60405180910390a350505050565b81611fb733611acc565b1015611ff157604080518082018252600681526518989818181960d11b6020820152905162461bcd60e51b815261086e9190600401612c50565b611ffe82610eba33611acc565b33600081815260086020526040902091909155612022908390610ee6908690611e99565b6001600160a01b0384166000818152600e602090815260408083203380855292529182902093909355519091907ecd77abc69e7bbb6de9df8cbfcca8720df3a30decf9eefd187e72ab2ea2f5139061207d9086908690613403565b60405180910390a3505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146120d35760405162461bcd60e51b815260040161086e9190612c50565b506009805460ff60b01b1916600160b01b831515908102919091179091556040517fa0c691180b8089c0c84e478ee67d6325768666cd889f13de016771c6f7af1f8890600090a250565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146121665760405162461bcd60e51b815260040161086e9190612c50565b50816121728686611e99565b10156121ac57604080518082018252600681526531313132303160d01b6020820152905162461bcd60e51b815261086e9190600401612c50565b6121ba82610eba8787611e99565b6001600160a01b038087166000908152600e60209081526040808320938916835292905220556121ed82610ee685611acc565b60086000856001600160a01b03166001600160a01b0316815260200190815260200160002081905550846001600160a01b0316846001600160a01b03167f7a1a1088c929a111dda2dc0ca1cc650aa78525d11fd3089abf20c8474f5d82cc85858560405161225d939291906131d3565b60405180910390a35050505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146122b55760405162461bcd60e51b815260040161086e9190612c50565b50601255565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146123045760405162461bcd60e51b815260040161086e9190612c50565b506010611052828261324b565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461235a5760405162461bcd60e51b815260040161086e9190612c50565b506001600160a01b038216156123f857806123758385611e99565b10156123af57604080518082018252600681526531313131303160d01b6020820152905162461bcd60e51b815261086e9190600401612c50565b6123bd81610eba8486611e99565b6001600160a01b038084166000908152600e60209081526040808320938816835292905220556003546123f09082612aed565b600355612483565b6001600160a01b03831660009081526008602052604090205481111561244c57604080518082018252600681526518989898981960d11b6020820152905162461bcd60e51b815261086e9190600401612c50565b61245981610eba85611acc565b6001600160a01b03841660009081526008602052604090205560035461247f9082612aed565b6003555b816001600160a01b0316836001600160a01b0316336001600160a01b03167fee02732fab40ece8284c756220846dff4b8d32058b86b35b4f0459bf172fcef0846040516124d291815260200190565b60405180910390a4505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146125285760405162461bcd60e51b815260040161086e9190612c50565b5060408051808201909152600681526535303031303160d01b60208201526001600160a01b03821661256d5760405162461bcd60e51b815260040161086e9190612c50565b50600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146126125760405162461bcd60e51b815260040161086e9190612c50565b50600980546001600160a01b0319166001600160a01b0392909216919091179055565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461267e5760405162461bcd60e51b815260040161086e9190612c50565b5060098054911515600160a01b0260ff60a01b19909216919091179055565b600c81815481106126ad57600080fd5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509116919060ff1684565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461272f5760405162461bcd60e51b815260040161086e9190612c50565b506001600160a01b038216156127885761274d81610ee68486611e99565b6001600160a01b038084166000908152600e60209081526040808320938816835292905220556003546127809082612b00565b6003556127bf565b61279581610ee685611acc565b6001600160a01b0384166000908152600860205260409020556003546127bb9082612b00565b6003555b816001600160a01b0316836001600160a01b0316336001600160a01b03167f65adeb76912378393e600cb6f64f3310842a42e1eae86273dc775d0c47a0f2dc846040516124d291815260200190565b60045460408051808201909152600681526531313033303160d01b60208201526000916001600160a01b0386811691161461285c5760405162461bcd60e51b815260040161086e9190612c50565b5061286a83610eba33611acc565b3360009081526008602052604090205561288783610ee686611acc565b6001600160a01b0385166000818152600860205260409081902092909255905163607705c560e11b815285919063c0ee0b8a906128cc903390889088906004016131d3565b600060405180830381600087803b1580156128e657600080fd5b505af11580156128fa573d6000803e3d6000fd5b50506040518681526001600160a01b038816925033915060008051602061341d83398151915290602001610fe9565b6004546000906001600160a01b0316331480159061294e5750600b5460ff1615156001145b1561298757604080518082018252600681526531313032303160d01b6020820152905162461bcd60e51b815261086e9190600401612c50565b6000546001600160a01b038581169116148015906129b35750600954600160a01b900460ff1615156001145b15612a725760095460005460405163d3da927f60e01b81526001600160a01b038781166004830152918216602482015291169063d3da927f90604401602060405180830381865afa158015612a0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a30919061330b565b60408051808201909152600681526518989819181960d11b6020820152901515600114612a705760405162461bcd60e51b815260040161086e9190612c50565b505b612a7f83610eba33611acc565b33600090815260086020526040902055612a9c83610ee686611acc565b6001600160a01b03851660008181526008602052604090819020929092559051339060008051602061341d83398151915290612adb9087815260200190565b60405180910390a35060019392505050565b6000612af9828461315a565b9392505050565b6000612af98284613147565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612b4b57612b4b612b0c565b604052919050565b600082601f830112612b6457600080fd5b813567ffffffffffffffff811115612b7e57612b7e612b0c565b612b91601f8201601f1916602001612b22565b818152846020838601011115612ba657600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215612bd657600080fd5b82359150602083013567ffffffffffffffff811115612bf457600080fd5b612c0085828601612b53565b9150509250929050565b6000815180845260005b81811015612c3057602081850181015186830182015201612c14565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000612af96020830184612c0a565b600067ffffffffffffffff821115612c7d57612c7d612b0c565b5060051b60200190565b80356001600160a01b0381168114612c9e57600080fd5b919050565b600082601f830112612cb457600080fd5b81356020612cc9612cc483612c63565b612b22565b8083825260208201915060208460051b870101935086841115612ceb57600080fd5b602086015b84811015612d075780358352918301918301612cf0565b509695505050505050565b60008060408385031215612d2557600080fd5b823567ffffffffffffffff80821115612d3d57600080fd5b818501915085601f830112612d5157600080fd5b81356020612d61612cc483612c63565b82815260059290921b84018101918181019089841115612d8057600080fd5b948201945b83861015612da557612d9686612c87565b82529482019490820190612d85565b96505086013592505080821115612dbb57600080fd5b50612c0085828601612ca3565b8015158114612dd657600080fd5b50565b600060208284031215612deb57600080fd5b8135612af981612dc8565b600080600060608486031215612e0b57600080fd5b612e1484612c87565b9250612e2260208501612c87565b9150604084013590509250925092565b600060208284031215612e4457600080fd5b813567ffffffffffffffff811115612e5b57600080fd5b612e6784828501612b53565b949350505050565b600060208284031215612e8157600080fd5b612af982612c87565b600060208284031215612e9c57600080fd5b813560ff81168114612af957600080fd5b60008060408385031215612ec057600080fd5b612ec983612c87565b946020939093013593505050565b600080600060608486031215612eec57600080fd5b612ef584612c87565b925060208401359150604084013567ffffffffffffffff811115612f1857600080fd5b612f2486828701612b53565b9150509250925092565b838152606060208201526000612f476060830185612c0a565b8281036040840152612f598185612c0a565b9695505050505050565b838152826020820152606060408201526000612f826060830184612c0a565b95945050505050565b600080600060608486031215612fa057600080fd5b83359250602084013567ffffffffffffffff80821115612fbf57600080fd5b612fcb87838801612b53565b93506040860135915080821115612fe157600080fd5b50612f2486828701612b53565b6000806040838503121561300157600080fd5b61300a83612c87565b915061301860208401612c87565b90509250929050565b6000806000806080858703121561303757600080fd5b61304085612c87565b935061304e60208601612c87565b925060408501359150606085013567ffffffffffffffff81111561307157600080fd5b61307d87828801612b53565b91505092959194509250565b600080600080600060a086880312156130a157600080fd5b6130aa86612c87565b94506130b860208701612c87565b93506130c660408701612c87565b925060608601359150608086013567ffffffffffffffff8111156130e957600080fd5b6130f588828901612b53565b9150509295509295909350565b60006020828403121561311457600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610d7e57610d7e613131565b81810381811115610d7e57610d7e613131565b6001600160a01b03848116825283166020820152606060408201819052600090612f8290830184612c0a565b600181811c908216806131ad57607f821691505b6020821081036131cd57634e487b7160e01b600052602260045260246000fd5b50919050565b60018060a01b0384168152826020820152606060408201526000612f826060830184612c0a565b601f821115613246576000816000526020600020601f850160051c810160208610156132235750805b601f850160051c820191505b818110156132425782815560010161322f565b5050505b505050565b815167ffffffffffffffff81111561326557613265612b0c565b613279816132738454613199565b846131fa565b602080601f8311600181146132ae57600084156132965750858301515b600019600386901b1c1916600185901b178555613242565b600085815260208120601f198616915b828110156132dd578886015182559484019460019091019084016132be565b50858210156132fb5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006020828403121561331d57600080fd5b8151612af981612dc8565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612f5990830184612c0a565b6000815461336881613199565b808552602060018381168015613385576001811461339f576133cd565b60ff1985168884015283151560051b8801830195506133cd565b866000528260002060005b858110156133c55781548a82018601529083019084016133aa565b890184019650505b505050505092915050565b8381526060602082015260006133f1606083018561335b565b8281036040840152612f59818561335b565b828152604060208201526000612e676040830184612c0a56feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212201889db3f768c3826c5ce92020d70f772bf2f23adad1ce1774ab7ed5a27c863ee64736f6c63430008170033"
}
\ No newline at end of file
diff --git a/contracts/IbetStraightBond.json b/contracts/IbetStraightBond.json
index 25541faa..d437a9ee 100644
--- a/contracts/IbetStraightBond.json
+++ b/contracts/IbetStraightBond.json
@@ -1092,6 +1092,19 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [],
+ "name": "requirePersonalInfoRegistered",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [],
"name": "returnAmount",
@@ -1274,6 +1287,19 @@
"stateMutability": "nonpayable",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "bool",
+ "name": "_requireRegistered",
+ "type": "bool"
+ }
+ ],
+ "name": "setRequirePersonalInfoRegistered",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -1499,6 +1525,6 @@
"type": "function"
}
],
- "bytecode": "60806040523480156200001157600080fd5b5060405162003918380380620039188339810160408190526200003491620001e2565b600080546001600160a01b0319908116339182161717905560016200005a8c826200041e565b506002620000698b826200041e565b506003899055600f88905560196200008288826200041e565b5060126200009187826200041e565b506013859055601b620000a585826200041e565b506014620000b484826200041e565b506015620000c383826200041e565b506016620000d282826200041e565b5050600354600080546001600160a01b031681526008602052604090205550506018805460ff1990811690915560078054909116600117905550620004ea9650505050505050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014257600080fd5b81516001600160401b03808211156200015f576200015f6200011a565b604051601f8301601f19908116603f011681019082821181831017156200018a576200018a6200011a565b8160405283815260209250866020858801011115620001a857600080fd5b600091505b83821015620001cc5785820183015181830184015290820190620001ad565b6000602085830101528094505050505092915050565b60008060008060008060008060008060006101608c8e0312156200020557600080fd5b8b516001600160401b038111156200021c57600080fd5b6200022a8e828f0162000130565b60208e0151909c5090506001600160401b038111156200024957600080fd5b620002578e828f0162000130565b9a505060408c0151985060608c0151975060808c015160018060401b038111156200028157600080fd5b6200028f8e828f0162000130565b60a08e015190985090506001600160401b03811115620002ae57600080fd5b620002bc8e828f0162000130565b60c08e015160e08f0151919850965090506001600160401b03811115620002e257600080fd5b620002f08e828f0162000130565b6101008e015190955090506001600160401b038111156200031057600080fd5b6200031e8e828f0162000130565b6101208e015190945090506001600160401b038111156200033e57600080fd5b6200034c8e828f0162000130565b6101408e015190935090506001600160401b038111156200036c57600080fd5b6200037a8e828f0162000130565b9150509295989b509295989b9093969950565b600181811c90821680620003a257607f821691505b602082108103620003c357634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000419576000816000526020600020601f850160051c81016020861015620003f45750805b601f850160051c820191505b81811015620004155782815560010162000400565b5050505b505050565b81516001600160401b038111156200043a576200043a6200011a565b62000452816200044b84546200038d565b84620003c9565b602080601f8311600181146200048a5760008415620004715750858301515b600019600386901b1c1916600185901b17855562000415565b600085815260208120601f198616915b82811015620004bb578886015182559484019460019091019084016200049a565b5085821015620004da5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b61341e80620004fa6000396000f3fe608060405234801561001057600080fd5b50600436106103db5760003560e01c806376fa7a311161020a578063b9b3e06a11610125578063ed62c2a0116100b8578063f35eeaef11610087578063f35eeaef14610818578063f7502a7c14610820578063fc590d0914610833578063fef1b9c01461083b578063ff12dcea1461087b57600080fd5b8063ed62c2a0146107e1578063ef4474cd146107e9578063ef8032ef146107f2578063f2fde38b1461080557600080fd5b8063ca5cbbb5116100f4578063ca5cbbb514610788578063d5d9d0c71461079b578063db20266f146107a3578063e7464db1146107ce57600080fd5b8063b9b3e06a1461073c578063bfe30fb01461074f578063c267ce5f14610762578063c7109ec91461077557600080fd5b80639301a78b1161019d578063a9059cbb1161016c578063a9059cbb146106ef578063ab62f92e14610702578063b2a90a6014610715578063b967a52e1461072957600080fd5b80639301a78b1461069f57806395d89b41146106c157806397e4c513146106c95780639cd23707146106dc57600080fd5b80638da5cb5b116101d95780638da5cb5b146106525780638ed8a9bc14610665578063919fe52d1461067857806392ff0d311461068b57600080fd5b806376fa7a31146106035780637c3a00fd1461061657806381ebdd791461061f5780638ac08bf11461063f57600080fd5b80633a2b6939116102fa5780635c40f6f41161028d5780636666e49c1161025c5780636666e49c146105d35780636f3b993f146105db57806370740aab146105e857806370a08231146105f057600080fd5b80635c40f6f4146105875780635ccef3e71461059a5780635f84f302146105ad57806363783444146105c057600080fd5b8063428630f6116102c9578063428630f61461056657806344fd9caa1461056e57806358c3b8701461057757806359d936171461057f57600080fd5b80633a2b6939146105255780633b18b9841461052d57806340615cf81461054057806340eba90e1461055357600080fd5b806323b872dd116103725780632e0ad004116103415780632e0ad004146104fa57806331cef44714610502578063329dbddc1461051557806336f7ab5e1461051d57600080fd5b806323b872dd146104a157806325287d42146104b457806325d60861146104c757806327e235e3146104da57600080fd5b8063153a1f3e116103ae578063153a1f3e1461045757806318160ddd1461046a5780631935a88014610481578063200d2ed21461049457600080fd5b8063034f6b21146103e057806306eaa0b71461040257806306fdde03146104175780630af7eb0f1461042c575b600080fd5b6018546103ed9060ff1681565b60405190151581526020015b60405180910390f35b610415610410366004612cc8565b61088e565b005b61041f610b58565b6040516103f99190612d55565b60095461043f906001600160a01b031681565b6040516001600160a01b0390911681526020016103f9565b6103ed610465366004612e17565b610be6565b61047360035481565b6040519081526020016103f9565b61041561048f366004612ede565b610de9565b6007546103ed9060ff1681565b6103ed6104af366004612efb565b610e7b565b60045461043f906001600160a01b031681565b6104156104d5366004612f37565b611062565b6104736104e8366004612f74565b60086020526000908152604090205481565b61041f6110bc565b610415610510366004612cc8565b6110c9565b61041f61122d565b61041f61123a565b61041f611247565b61041561053b366004612f8f565b611254565b61041561054e366004612fa8565b6112d3565b610415610561366004612fd2565b611371565b61041f61163c565b610473600f5481565b61041f611649565b61041f611656565b610415610595366004612ede565b611663565b6104156105a8366004612cc8565b6116f2565b6104156105bb366004612f8f565b611a74565b6104156105ce366004612f37565b611ac3565b61041f611b19565b600b546103ed9060ff1681565b61041f611b26565b6104736105fe366004612f74565b611b33565b610415610611366004612f74565b611b4e565b61047360105481565b61047361062d366004612f74565b600d6020526000908152604090205481565b61041561064d366004612f37565b611bba565b60005461043f906001600160a01b031681565b610415610673366004612f37565b611c10565b610415610686366004612f37565b611c66565b6009546103ed90600160a01b900460ff1681565b6106b26106ad366004612f74565b611cbc565b6040516103f993929190613029565b61041f611d67565b6104156106d7366004612f37565b611d74565b6104156106ea366004612ede565b611dca565b6103ed6106fd366004612fa8565b611e32565b610415610710366004612f37565b611ef3565b6009546103ed90600160a81b900460ff1681565b610415610737366004612f37565b611f49565b61047361074a366004613051565b611f9f565b61041561075d366004613084565b611fca565b610415610770366004612fd2565b6120b3565b610415610783366004612ede565b612190565b6104156107963660046130ec565b612223565b610415612372565b6104736107b1366004613051565b600e60209081526000928352604080842090915290825290205481565b6104156107dc366004612efb565b6123f4565b61041f6125c2565b61047360135481565b610415610800366004612f8f565b6125cf565b610415610813366004612f74565b61264e565b61041f612738565b61041561082e366004612f74565b612745565b61041f6127b1565b61084e610849366004612f8f565b6127be565b604080516001600160a01b03958616815294909316602085015291830152151560608201526080016103f9565b610415610889366004612efb565b612807565b336001600160a01b0316600c83815481106108ab576108ab613165565b60009182526020909120600490910201546001600160a01b0316148015906108de57506000546001600160a01b03163314155b1561092057604080518082018252600681526531323038303160d01b6020820152905162461bcd60e51b81526109179190600401612d55565b60405180910390fd5b600c828154811061093357610933613165565b6000918252602082206003600490920201015460ff16151590036109855760408051808201825260068152651899181c181960d11b6020820152905162461bcd60e51b81526109179190600401612d55565b600c828154811061099857610998613165565b90600052602060002090600402016002015460086000600c85815481106109c1576109c1613165565b600091825260208083206004909202909101546001600160a01b03168352820192909252604001812080549091906109fa908490613191565b9091555050600c805483908110610a1357610a13613165565b906000526020600020906004020160020154600d6000600c8581548110610a3c57610a3c613165565b600091825260208083206004909202909101546001600160a01b0316835282019290925260400181208054909190610a759084906131a4565b925050819055506000600c8381548110610a9157610a91613165565b906000526020600020906004020160030160006101000a81548160ff021916908315150217905550817fa0cc3a4feb26502e6e6cd57b2113d58bdab80c6711d8252356be9a49945bb5f7600c8481548110610aee57610aee613165565b6000918252602090912060049091020154600c80546001600160a01b039092169186908110610b1f57610b1f613165565b6000918252602090912060016004909202010154604051610b4c92916001600160a01b03169086906131b7565b60405180910390a25050565b60018054610b65906131e3565b80601f0160208091040260200160405190810160405280929190818152602001828054610b91906131e3565b8015610bde5780601f10610bb357610100808354040283529160200191610bde565b820191906000526020600020905b815481529060010190602001808311610bc157829003601f168201915b505050505081565b60008151835114610c2557604080518082018252600681526531323035303160d01b6020820152905162461bcd60e51b81526109179190600401612d55565b6000805b8451811015610c6157838181518110610c4457610c44613165565b602002602001015182610c579190613191565b9150600101610c29565b5080610c6c33611b33565b1015610ca65760408051808201825260068152651899181a981960d11b6020820152905162461bcd60e51b81526109179190600401612d55565b6004546001600160a01b03163314610d075760095460408051808201909152600681526531323035303360d01b602082015290600160a01b900460ff161515600114610d055760405162461bcd60e51b81526004016109179190612d55565b505b606060006001935060005b8651811015610dde57610d3e878281518110610d3057610d30613165565b60200260200101513b151590565b15610d8757610d80878281518110610d5857610d58613165565b6020026020010151878381518110610d7257610d72613165565b60200260200101518561292f565b9150610dc7565b610dc4878281518110610d9c57610d9c613165565b6020026020010151878381518110610db657610db6613165565b602002602001015185612a4a565b91505b811515600003610dd657600094505b600101610d12565b505050505b92915050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314610e325760405162461bcd60e51b81526004016109179190612d55565b50600b805460ff19168215159081179091556040519081527fe1455bc53682229469d6919bb96d7b338cbffea93170dfb5f02242c22fb6d07f906020015b60405180910390a150565b6000805460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314610ec55760405162461bcd60e51b81526004016109179190612d55565b5081610ed085611b33565b1015610f0a57604080518082018252600681526531323036303160d01b6020820152905162461bcd60e51b81526109179190600401612d55565b6060833b15610fcf57610f2683610f2087611b33565b90612bf2565b6001600160a01b038616600090815260086020526040902055610f5283610f4c86611b33565b90612c05565b6001600160a01b0385166000818152600860205260409081902092909255905163607705c560e11b815285919063c0ee0b8a90610f979033908890879060040161321d565b600060405180830381600087803b158015610fb157600080fd5b505af1158015610fc5573d6000803e3d6000fd5b505050505061101c565b610fdc83610f2087611b33565b6001600160a01b03861660009081526008602052604090205561100283610f4c86611b33565b6001600160a01b0385166000908152600860205260409020555b836001600160a01b0316856001600160a01b03166000805160206133c98339815191528560405161104f91815260200190565b60405180910390a3506001949350505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146110ab5760405162461bcd60e51b81526004016109179190612d55565b5060176110b88282613295565b5050565b601a8054610b65906131e3565b60095460408051808201909152600681526531323130303160d01b602082015290600160a81b900460ff1615156001146111165760405162461bcd60e51b81526004016109179190612d55565b5060095460005460405163d3da927f60e01b81523360048201526001600160a01b03918216602482015291169063d3da927f90604401602060405180830381865afa158015611169573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118d9190613355565b60408051808201909152600681526518991898181960d11b60208201529015156001146111cd5760405162461bcd60e51b81526004016109179190612d55565b50336000908152600a602052604090208281556002016111ed8282613295565b507f3bb9553f633a7ecb4cbc5f9885e750a522496ce06deff1ed9184180ca83940c03383836040516112219392919061321d565b60405180910390a15050565b60118054610b65906131e3565b60058054610b65906131e3565b60198054610b65906131e3565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461129d5760405162461bcd60e51b81526004016109179190612d55565b5060138190556040518181527fe451abe602c33e612ea61221b5a142f7fe3c044286e42c8340ffe7fa86a5859790602001610e70565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461131c5760405162461bcd60e51b81526004016109179190612d55565b506001600160a01b0382166000818152600a6020908152604091829020600101849055815192835282018390527fa42bd6bdfcb8f9b815c68e4ce0e16dec3f1e7ac53967ee8309653de522a735b19101611221565b600b5460ff16158061138d5750600954600160a01b900460ff16155b8061139f57508161139d33611b33565b105b156113d857604080518082018252600681526531323037303160d01b6020820152905162461bcd60e51b81526109179190600401612d55565b6000546001600160a01b038481169116146114a75760095460005460405163d3da927f60e01b81526001600160a01b038681166004830152918216602482015291169063d3da927f90604401602060405180830381865afa158015611441573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114659190613355565b6040805180820190915260068152651899181b981960d11b60208201529015156001146114a55760405162461bcd60e51b81526004016109179190612d55565b505b33600090815260086020526040812080548492906114c69084906131a4565b9091555050336000908152600d6020526040812080548492906114ea908490613191565b9091555050600c805460408051608081018252338082526001600160a01b038881166020840190815283850189815260016060860181815290880189556000989098529351600487027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7810180549285166001600160a01b031993841617905591517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c8830180549190941691161790915591517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c983015593517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8ca909101805491151560ff1990921691909117905551909182917fa256c3bc72c26fbfd6285cfde8c7e345b4d0c7ccfc725d103e9f129c5d8a039a9161162e91889088908890613372565b60405180910390a250505050565b60068054610b65906131e3565b60178054610b65906131e3565b601b8054610b65906131e3565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146116ac5760405162461bcd60e51b81526004016109179190612d55565b506007805460ff191682151590811790915560405160ff9091161515907fe1e5c6f5867805bf3fab73f4df4b80d0e87e9262a7bc22ac7c2cb3fd5896222f90600090a250565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461173b5760405162461bcd60e51b81526004016109179190612d55565b50600954600160a01b900460ff16151560000361178657604080518082018252600681526531323039303160d01b6020820152905162461bcd60e51b81526109179190600401612d55565b600c828154811061179957611799613165565b6000918252602082206003600490920201015460ff16151590036117eb5760408051808201825260068152651899181c981960d11b6020820152905162461bcd60e51b81526109179190600401612d55565b600c82815481106117fe576117fe613165565b90600052602060002090600402016002015460086000600c858154811061182757611827613165565b60009182526020808320600160049093020191909101546001600160a01b0316835282019290925260400181208054909190611864908490613191565b9091555050600c80548390811061187d5761187d613165565b906000526020600020906004020160020154600d6000600c85815481106118a6576118a6613165565b600091825260208083206004909202909101546001600160a01b03168352820192909252604001812080549091906118df9084906131a4565b925050819055506000600c83815481106118fb576118fb613165565b906000526020600020906004020160030160006101000a81548160ff021916908315150217905550817f6b50d6e4941ce7ae74ed7f7f51df5fb7680754c2815a094c66bea5ca80a40eb1600c848154811061195857611958613165565b6000918252602090912060049091020154600c80546001600160a01b03909216918690811061198957611989613165565b60009182526020909120600160049092020101546040516119b692916001600160a01b03169086906131b7565b60405180910390a2600c82815481106119d1576119d1613165565b6000918252602090912060016004909202010154600c80546001600160a01b039092169184908110611a0557611a05613165565b6000918252602090912060049091020154600c80546001600160a01b03909216916000805160206133c9833981519152919086908110611a4757611a47613165565b906000526020600020906004020160020154604051611a6891815260200190565b60405180910390a35050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611abd5760405162461bcd60e51b81526004016109179190612d55565b50601055565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611b0c5760405162461bcd60e51b81526004016109179190612d55565b5060116110b88282613295565b60128054610b65906131e3565b60168054610b65906131e3565b6001600160a01b031660009081526008602052604090205490565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611b975760405162461bcd60e51b81526004016109179190612d55565b50600480546001600160a01b0319166001600160a01b0392909216919091179055565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611c035760405162461bcd60e51b81526004016109179190612d55565b5060196110b88282613295565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611c595760405162461bcd60e51b81526004016109179190612d55565b5060066110b88282613295565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611caf5760405162461bcd60e51b81526004016109179190612d55565b50601b6110b88282613295565b600a6020526000908152604090208054600182015460028301805492939192611ce4906131e3565b80601f0160208091040260200160405190810160405280929190818152602001828054611d10906131e3565b8015611d5d5780601f10611d3257610100808354040283529160200191611d5d565b820191906000526020600020905b815481529060010190602001808311611d4057829003601f168201915b5050505050905083565b60028054610b65906131e3565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611dbd5760405162461bcd60e51b81526004016109179190612d55565b50601c6110b88282613295565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611e135760405162461bcd60e51b81526004016109179190612d55565b5060098054911515600160a01b0260ff60a01b19909216919091179055565b600081611e3e33611b33565b10156040518060400160405280600681526020016531323034303160d01b81525090611e7d5760405162461bcd60e51b81526004016109179190612d55565b506009546040805180820190915260068152651899181a181960d11b602082015290600160a01b900460ff161515600114611ecb5760405162461bcd60e51b81526004016109179190612d55565b506060833b15611ee857611ee084848361292f565b915050610de3565b611ee0848483612a4a565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611f3c5760405162461bcd60e51b81526004016109179190612d55565b50601a6110b88282613295565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611f925760405162461bcd60e51b81526004016109179190612d55565b5060056110b88282613295565b6001600160a01b039182166000908152600e6020908152604080832093909416825291909152205490565b81611fd53386611f9f565b101561200f57604080518082018252600681526518991818981960d11b6020820152905162461bcd60e51b81526109179190600401612d55565b61201d82610f203387611f9f565b336000908152600e602090815260408083206001600160a01b038916845290915290205561204e82610f4c85611b33565b6001600160a01b038085166000908152600860205260409081902092909255905133918616907f7a1a1088c929a111dda2dc0ca1cc650aa78525d11fd3089abf20c8474f5d82cc906120a59087908790879061321d565b60405180910390a350505050565b816120bd33611b33565b10156120f757604080518082018252600681526518991818181960d11b6020820152905162461bcd60e51b81526109179190600401612d55565b61210482610f2033611b33565b33600081815260086020526040902091909155612128908390610f4c908690611f9f565b6001600160a01b0384166000818152600e602090815260408083203380855292529182902093909355519091907ecd77abc69e7bbb6de9df8cbfcca8720df3a30decf9eefd187e72ab2ea2f5139061218390869086906133af565b60405180910390a3505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146121d95760405162461bcd60e51b81526004016109179190612d55565b506009805460ff60a81b1916600160a81b831515908102919091179091556040517fa0c691180b8089c0c84e478ee67d6325768666cd889f13de016771c6f7af1f8890600090a250565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461226c5760405162461bcd60e51b81526004016109179190612d55565b50816122788686611f9f565b10156122b257604080518082018252600681526531323132303160d01b6020820152905162461bcd60e51b81526109179190600401612d55565b6122c082610f208787611f9f565b6001600160a01b038087166000908152600e60209081526040808320938916835292905220556122f382610f4c85611b33565b60086000856001600160a01b03166001600160a01b0316815260200190815260200160002081905550846001600160a01b0316846001600160a01b03167f7a1a1088c929a111dda2dc0ca1cc650aa78525d11fd3089abf20c8474f5d82cc8585856040516123639392919061321d565b60405180910390a35050505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146123bb5760405162461bcd60e51b81526004016109179190612d55565b506018805460ff191660011790556040517f96151d7f1d8c50be29a45c0e3ae9ce2008888d1615b196e8f5ffd8c178e6dde890600090a1565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461243d5760405162461bcd60e51b81526004016109179190612d55565b506001600160a01b038216156124db57806124588385611f9f565b101561249257604080518082018252600681526531323131303160d01b6020820152905162461bcd60e51b81526109179190600401612d55565b6124a081610f208486611f9f565b6001600160a01b038084166000908152600e60209081526040808320938816835292905220556003546124d39082612bf2565b600355612566565b6001600160a01b03831660009081526008602052604090205481111561252f57604080518082018252600681526518991898981960d11b6020820152905162461bcd60e51b81526109179190600401612d55565b61253c81610f2085611b33565b6001600160a01b0384166000908152600860205260409020556003546125629082612bf2565b6003555b816001600160a01b0316836001600160a01b0316336001600160a01b03167fee02732fab40ece8284c756220846dff4b8d32058b86b35b4f0459bf172fcef0846040516125b591815260200190565b60405180910390a4505050565b601c8054610b65906131e3565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146126185760405162461bcd60e51b81526004016109179190612d55565b50600f8190556040518181527f82b19c9a00131a87eeff1903fcb9e4f2a3ba76dd86098586eea921a533e218dc90602001610e70565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146126975760405162461bcd60e51b81526004016109179190612d55565b5060408051808201909152600681526535303031303160d01b60208201526001600160a01b0382166126dc5760405162461bcd60e51b81526004016109179190612d55565b50600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60158054610b65906131e3565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461278e5760405162461bcd60e51b81526004016109179190612d55565b50600980546001600160a01b0319166001600160a01b0392909216919091179055565b60148054610b65906131e3565b600c81815481106127ce57600080fd5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509116919060ff1684565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146128505760405162461bcd60e51b81526004016109179190612d55565b506001600160a01b038216156128a95761286e81610f4c8486611f9f565b6001600160a01b038084166000908152600e60209081526040808320938816835292905220556003546128a19082612c05565b6003556128e0565b6128b681610f4c85611b33565b6001600160a01b0384166000908152600860205260409020556003546128dc9082612c05565b6003555b816001600160a01b0316836001600160a01b0316336001600160a01b03167f65adeb76912378393e600cb6f64f3310842a42e1eae86273dc775d0c47a0f2dc846040516125b591815260200190565b60045460408051808201909152600681526531323033303160d01b60208201526000916001600160a01b0386811691161461297d5760405162461bcd60e51b81526004016109179190612d55565b5061298b83610f2033611b33565b336000908152600860205260409020556129a883610f4c86611b33565b6001600160a01b0385166000818152600860205260409081902092909255905163607705c560e11b815285919063c0ee0b8a906129ed9033908890889060040161321d565b600060405180830381600087803b158015612a0757600080fd5b505af1158015612a1b573d6000803e3d6000fd5b50506040518681526001600160a01b03881692503391506000805160206133c98339815191529060200161104f565b6004546000906001600160a01b03163314801590612a6f5750600b5460ff1615156001145b15612aa857604080518082018252600681526531323032303160d01b6020820152905162461bcd60e51b81526109179190600401612d55565b6000546001600160a01b03858116911614612b775760095460005460405163d3da927f60e01b81526001600160a01b038781166004830152918216602482015291169063d3da927f90604401602060405180830381865afa158015612b11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b359190613355565b60408051808201909152600681526518991819181960d11b6020820152901515600114612b755760405162461bcd60e51b81526004016109179190612d55565b505b612b8483610f2033611b33565b33600090815260086020526040902055612ba183610f4c86611b33565b6001600160a01b0385166000818152600860205260409081902092909255905133906000805160206133c983398151915290612be09087815260200190565b60405180910390a35060019392505050565b6000612bfe82846131a4565b9392505050565b6000612bfe8284613191565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612c5057612c50612c11565b604052919050565b600082601f830112612c6957600080fd5b813567ffffffffffffffff811115612c8357612c83612c11565b612c96601f8201601f1916602001612c27565b818152846020838601011115612cab57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215612cdb57600080fd5b82359150602083013567ffffffffffffffff811115612cf957600080fd5b612d0585828601612c58565b9150509250929050565b6000815180845260005b81811015612d3557602081850181015186830182015201612d19565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000612bfe6020830184612d0f565b600067ffffffffffffffff821115612d8257612d82612c11565b5060051b60200190565b80356001600160a01b0381168114612da357600080fd5b919050565b600082601f830112612db957600080fd5b81356020612dce612dc983612d68565b612c27565b8083825260208201915060208460051b870101935086841115612df057600080fd5b602086015b84811015612e0c5780358352918301918301612df5565b509695505050505050565b60008060408385031215612e2a57600080fd5b823567ffffffffffffffff80821115612e4257600080fd5b818501915085601f830112612e5657600080fd5b81356020612e66612dc983612d68565b82815260059290921b84018101918181019089841115612e8557600080fd5b948201945b83861015612eaa57612e9b86612d8c565b82529482019490820190612e8a565b96505086013592505080821115612ec057600080fd5b50612d0585828601612da8565b8015158114612edb57600080fd5b50565b600060208284031215612ef057600080fd5b8135612bfe81612ecd565b600080600060608486031215612f1057600080fd5b612f1984612d8c565b9250612f2760208501612d8c565b9150604084013590509250925092565b600060208284031215612f4957600080fd5b813567ffffffffffffffff811115612f6057600080fd5b612f6c84828501612c58565b949350505050565b600060208284031215612f8657600080fd5b612bfe82612d8c565b600060208284031215612fa157600080fd5b5035919050565b60008060408385031215612fbb57600080fd5b612fc483612d8c565b946020939093013593505050565b600080600060608486031215612fe757600080fd5b612ff084612d8c565b925060208401359150604084013567ffffffffffffffff81111561301357600080fd5b61301f86828701612c58565b9150509250925092565b8381528260208201526060604082015260006130486060830184612d0f565b95945050505050565b6000806040838503121561306457600080fd5b61306d83612d8c565b915061307b60208401612d8c565b90509250929050565b6000806000806080858703121561309a57600080fd5b6130a385612d8c565b93506130b160208601612d8c565b925060408501359150606085013567ffffffffffffffff8111156130d457600080fd5b6130e087828801612c58565b91505092959194509250565b600080600080600060a0868803121561310457600080fd5b61310d86612d8c565b945061311b60208701612d8c565b935061312960408701612d8c565b925060608601359150608086013567ffffffffffffffff81111561314c57600080fd5b61315888828901612c58565b9150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610de357610de361317b565b81810381811115610de357610de361317b565b6001600160a01b0384811682528316602082015260606040820181905260009061304890830184612d0f565b600181811c908216806131f757607f821691505b60208210810361321757634e487b7160e01b600052602260045260246000fd5b50919050565b60018060a01b03841681528260208201526060604082015260006130486060830184612d0f565b601f821115613290576000816000526020600020601f850160051c8101602086101561326d5750805b601f850160051c820191505b8181101561328c57828155600101613279565b5050505b505050565b815167ffffffffffffffff8111156132af576132af612c11565b6132c3816132bd84546131e3565b84613244565b602080601f8311600181146132f857600084156132e05750858301515b600019600386901b1c1916600185901b17855561328c565b600085815260208120601f198616915b8281101561332757888601518255948401946001909101908401613308565b50858210156133455787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006020828403121561336757600080fd5b8151612bfe81612ecd565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906133a590830184612d0f565b9695505050505050565b828152604060208201526000612f6c6040830184612d0f56feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122088f29532258abd280c78b38a51851d03be753cbc68978a3c5f7fbc262f37bfa964736f6c63430008170033",
- "deployedBytecode": "608060405234801561001057600080fd5b50600436106103db5760003560e01c806376fa7a311161020a578063b9b3e06a11610125578063ed62c2a0116100b8578063f35eeaef11610087578063f35eeaef14610818578063f7502a7c14610820578063fc590d0914610833578063fef1b9c01461083b578063ff12dcea1461087b57600080fd5b8063ed62c2a0146107e1578063ef4474cd146107e9578063ef8032ef146107f2578063f2fde38b1461080557600080fd5b8063ca5cbbb5116100f4578063ca5cbbb514610788578063d5d9d0c71461079b578063db20266f146107a3578063e7464db1146107ce57600080fd5b8063b9b3e06a1461073c578063bfe30fb01461074f578063c267ce5f14610762578063c7109ec91461077557600080fd5b80639301a78b1161019d578063a9059cbb1161016c578063a9059cbb146106ef578063ab62f92e14610702578063b2a90a6014610715578063b967a52e1461072957600080fd5b80639301a78b1461069f57806395d89b41146106c157806397e4c513146106c95780639cd23707146106dc57600080fd5b80638da5cb5b116101d95780638da5cb5b146106525780638ed8a9bc14610665578063919fe52d1461067857806392ff0d311461068b57600080fd5b806376fa7a31146106035780637c3a00fd1461061657806381ebdd791461061f5780638ac08bf11461063f57600080fd5b80633a2b6939116102fa5780635c40f6f41161028d5780636666e49c1161025c5780636666e49c146105d35780636f3b993f146105db57806370740aab146105e857806370a08231146105f057600080fd5b80635c40f6f4146105875780635ccef3e71461059a5780635f84f302146105ad57806363783444146105c057600080fd5b8063428630f6116102c9578063428630f61461056657806344fd9caa1461056e57806358c3b8701461057757806359d936171461057f57600080fd5b80633a2b6939146105255780633b18b9841461052d57806340615cf81461054057806340eba90e1461055357600080fd5b806323b872dd116103725780632e0ad004116103415780632e0ad004146104fa57806331cef44714610502578063329dbddc1461051557806336f7ab5e1461051d57600080fd5b806323b872dd146104a157806325287d42146104b457806325d60861146104c757806327e235e3146104da57600080fd5b8063153a1f3e116103ae578063153a1f3e1461045757806318160ddd1461046a5780631935a88014610481578063200d2ed21461049457600080fd5b8063034f6b21146103e057806306eaa0b71461040257806306fdde03146104175780630af7eb0f1461042c575b600080fd5b6018546103ed9060ff1681565b60405190151581526020015b60405180910390f35b610415610410366004612cc8565b61088e565b005b61041f610b58565b6040516103f99190612d55565b60095461043f906001600160a01b031681565b6040516001600160a01b0390911681526020016103f9565b6103ed610465366004612e17565b610be6565b61047360035481565b6040519081526020016103f9565b61041561048f366004612ede565b610de9565b6007546103ed9060ff1681565b6103ed6104af366004612efb565b610e7b565b60045461043f906001600160a01b031681565b6104156104d5366004612f37565b611062565b6104736104e8366004612f74565b60086020526000908152604090205481565b61041f6110bc565b610415610510366004612cc8565b6110c9565b61041f61122d565b61041f61123a565b61041f611247565b61041561053b366004612f8f565b611254565b61041561054e366004612fa8565b6112d3565b610415610561366004612fd2565b611371565b61041f61163c565b610473600f5481565b61041f611649565b61041f611656565b610415610595366004612ede565b611663565b6104156105a8366004612cc8565b6116f2565b6104156105bb366004612f8f565b611a74565b6104156105ce366004612f37565b611ac3565b61041f611b19565b600b546103ed9060ff1681565b61041f611b26565b6104736105fe366004612f74565b611b33565b610415610611366004612f74565b611b4e565b61047360105481565b61047361062d366004612f74565b600d6020526000908152604090205481565b61041561064d366004612f37565b611bba565b60005461043f906001600160a01b031681565b610415610673366004612f37565b611c10565b610415610686366004612f37565b611c66565b6009546103ed90600160a01b900460ff1681565b6106b26106ad366004612f74565b611cbc565b6040516103f993929190613029565b61041f611d67565b6104156106d7366004612f37565b611d74565b6104156106ea366004612ede565b611dca565b6103ed6106fd366004612fa8565b611e32565b610415610710366004612f37565b611ef3565b6009546103ed90600160a81b900460ff1681565b610415610737366004612f37565b611f49565b61047361074a366004613051565b611f9f565b61041561075d366004613084565b611fca565b610415610770366004612fd2565b6120b3565b610415610783366004612ede565b612190565b6104156107963660046130ec565b612223565b610415612372565b6104736107b1366004613051565b600e60209081526000928352604080842090915290825290205481565b6104156107dc366004612efb565b6123f4565b61041f6125c2565b61047360135481565b610415610800366004612f8f565b6125cf565b610415610813366004612f74565b61264e565b61041f612738565b61041561082e366004612f74565b612745565b61041f6127b1565b61084e610849366004612f8f565b6127be565b604080516001600160a01b03958616815294909316602085015291830152151560608201526080016103f9565b610415610889366004612efb565b612807565b336001600160a01b0316600c83815481106108ab576108ab613165565b60009182526020909120600490910201546001600160a01b0316148015906108de57506000546001600160a01b03163314155b1561092057604080518082018252600681526531323038303160d01b6020820152905162461bcd60e51b81526109179190600401612d55565b60405180910390fd5b600c828154811061093357610933613165565b6000918252602082206003600490920201015460ff16151590036109855760408051808201825260068152651899181c181960d11b6020820152905162461bcd60e51b81526109179190600401612d55565b600c828154811061099857610998613165565b90600052602060002090600402016002015460086000600c85815481106109c1576109c1613165565b600091825260208083206004909202909101546001600160a01b03168352820192909252604001812080549091906109fa908490613191565b9091555050600c805483908110610a1357610a13613165565b906000526020600020906004020160020154600d6000600c8581548110610a3c57610a3c613165565b600091825260208083206004909202909101546001600160a01b0316835282019290925260400181208054909190610a759084906131a4565b925050819055506000600c8381548110610a9157610a91613165565b906000526020600020906004020160030160006101000a81548160ff021916908315150217905550817fa0cc3a4feb26502e6e6cd57b2113d58bdab80c6711d8252356be9a49945bb5f7600c8481548110610aee57610aee613165565b6000918252602090912060049091020154600c80546001600160a01b039092169186908110610b1f57610b1f613165565b6000918252602090912060016004909202010154604051610b4c92916001600160a01b03169086906131b7565b60405180910390a25050565b60018054610b65906131e3565b80601f0160208091040260200160405190810160405280929190818152602001828054610b91906131e3565b8015610bde5780601f10610bb357610100808354040283529160200191610bde565b820191906000526020600020905b815481529060010190602001808311610bc157829003601f168201915b505050505081565b60008151835114610c2557604080518082018252600681526531323035303160d01b6020820152905162461bcd60e51b81526109179190600401612d55565b6000805b8451811015610c6157838181518110610c4457610c44613165565b602002602001015182610c579190613191565b9150600101610c29565b5080610c6c33611b33565b1015610ca65760408051808201825260068152651899181a981960d11b6020820152905162461bcd60e51b81526109179190600401612d55565b6004546001600160a01b03163314610d075760095460408051808201909152600681526531323035303360d01b602082015290600160a01b900460ff161515600114610d055760405162461bcd60e51b81526004016109179190612d55565b505b606060006001935060005b8651811015610dde57610d3e878281518110610d3057610d30613165565b60200260200101513b151590565b15610d8757610d80878281518110610d5857610d58613165565b6020026020010151878381518110610d7257610d72613165565b60200260200101518561292f565b9150610dc7565b610dc4878281518110610d9c57610d9c613165565b6020026020010151878381518110610db657610db6613165565b602002602001015185612a4a565b91505b811515600003610dd657600094505b600101610d12565b505050505b92915050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314610e325760405162461bcd60e51b81526004016109179190612d55565b50600b805460ff19168215159081179091556040519081527fe1455bc53682229469d6919bb96d7b338cbffea93170dfb5f02242c22fb6d07f906020015b60405180910390a150565b6000805460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314610ec55760405162461bcd60e51b81526004016109179190612d55565b5081610ed085611b33565b1015610f0a57604080518082018252600681526531323036303160d01b6020820152905162461bcd60e51b81526109179190600401612d55565b6060833b15610fcf57610f2683610f2087611b33565b90612bf2565b6001600160a01b038616600090815260086020526040902055610f5283610f4c86611b33565b90612c05565b6001600160a01b0385166000818152600860205260409081902092909255905163607705c560e11b815285919063c0ee0b8a90610f979033908890879060040161321d565b600060405180830381600087803b158015610fb157600080fd5b505af1158015610fc5573d6000803e3d6000fd5b505050505061101c565b610fdc83610f2087611b33565b6001600160a01b03861660009081526008602052604090205561100283610f4c86611b33565b6001600160a01b0385166000908152600860205260409020555b836001600160a01b0316856001600160a01b03166000805160206133c98339815191528560405161104f91815260200190565b60405180910390a3506001949350505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146110ab5760405162461bcd60e51b81526004016109179190612d55565b5060176110b88282613295565b5050565b601a8054610b65906131e3565b60095460408051808201909152600681526531323130303160d01b602082015290600160a81b900460ff1615156001146111165760405162461bcd60e51b81526004016109179190612d55565b5060095460005460405163d3da927f60e01b81523360048201526001600160a01b03918216602482015291169063d3da927f90604401602060405180830381865afa158015611169573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118d9190613355565b60408051808201909152600681526518991898181960d11b60208201529015156001146111cd5760405162461bcd60e51b81526004016109179190612d55565b50336000908152600a602052604090208281556002016111ed8282613295565b507f3bb9553f633a7ecb4cbc5f9885e750a522496ce06deff1ed9184180ca83940c03383836040516112219392919061321d565b60405180910390a15050565b60118054610b65906131e3565b60058054610b65906131e3565b60198054610b65906131e3565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461129d5760405162461bcd60e51b81526004016109179190612d55565b5060138190556040518181527fe451abe602c33e612ea61221b5a142f7fe3c044286e42c8340ffe7fa86a5859790602001610e70565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461131c5760405162461bcd60e51b81526004016109179190612d55565b506001600160a01b0382166000818152600a6020908152604091829020600101849055815192835282018390527fa42bd6bdfcb8f9b815c68e4ce0e16dec3f1e7ac53967ee8309653de522a735b19101611221565b600b5460ff16158061138d5750600954600160a01b900460ff16155b8061139f57508161139d33611b33565b105b156113d857604080518082018252600681526531323037303160d01b6020820152905162461bcd60e51b81526109179190600401612d55565b6000546001600160a01b038481169116146114a75760095460005460405163d3da927f60e01b81526001600160a01b038681166004830152918216602482015291169063d3da927f90604401602060405180830381865afa158015611441573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114659190613355565b6040805180820190915260068152651899181b981960d11b60208201529015156001146114a55760405162461bcd60e51b81526004016109179190612d55565b505b33600090815260086020526040812080548492906114c69084906131a4565b9091555050336000908152600d6020526040812080548492906114ea908490613191565b9091555050600c805460408051608081018252338082526001600160a01b038881166020840190815283850189815260016060860181815290880189556000989098529351600487027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7810180549285166001600160a01b031993841617905591517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c8830180549190941691161790915591517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c983015593517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8ca909101805491151560ff1990921691909117905551909182917fa256c3bc72c26fbfd6285cfde8c7e345b4d0c7ccfc725d103e9f129c5d8a039a9161162e91889088908890613372565b60405180910390a250505050565b60068054610b65906131e3565b60178054610b65906131e3565b601b8054610b65906131e3565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146116ac5760405162461bcd60e51b81526004016109179190612d55565b506007805460ff191682151590811790915560405160ff9091161515907fe1e5c6f5867805bf3fab73f4df4b80d0e87e9262a7bc22ac7c2cb3fd5896222f90600090a250565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461173b5760405162461bcd60e51b81526004016109179190612d55565b50600954600160a01b900460ff16151560000361178657604080518082018252600681526531323039303160d01b6020820152905162461bcd60e51b81526109179190600401612d55565b600c828154811061179957611799613165565b6000918252602082206003600490920201015460ff16151590036117eb5760408051808201825260068152651899181c981960d11b6020820152905162461bcd60e51b81526109179190600401612d55565b600c82815481106117fe576117fe613165565b90600052602060002090600402016002015460086000600c858154811061182757611827613165565b60009182526020808320600160049093020191909101546001600160a01b0316835282019290925260400181208054909190611864908490613191565b9091555050600c80548390811061187d5761187d613165565b906000526020600020906004020160020154600d6000600c85815481106118a6576118a6613165565b600091825260208083206004909202909101546001600160a01b03168352820192909252604001812080549091906118df9084906131a4565b925050819055506000600c83815481106118fb576118fb613165565b906000526020600020906004020160030160006101000a81548160ff021916908315150217905550817f6b50d6e4941ce7ae74ed7f7f51df5fb7680754c2815a094c66bea5ca80a40eb1600c848154811061195857611958613165565b6000918252602090912060049091020154600c80546001600160a01b03909216918690811061198957611989613165565b60009182526020909120600160049092020101546040516119b692916001600160a01b03169086906131b7565b60405180910390a2600c82815481106119d1576119d1613165565b6000918252602090912060016004909202010154600c80546001600160a01b039092169184908110611a0557611a05613165565b6000918252602090912060049091020154600c80546001600160a01b03909216916000805160206133c9833981519152919086908110611a4757611a47613165565b906000526020600020906004020160020154604051611a6891815260200190565b60405180910390a35050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611abd5760405162461bcd60e51b81526004016109179190612d55565b50601055565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611b0c5760405162461bcd60e51b81526004016109179190612d55565b5060116110b88282613295565b60128054610b65906131e3565b60168054610b65906131e3565b6001600160a01b031660009081526008602052604090205490565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611b975760405162461bcd60e51b81526004016109179190612d55565b50600480546001600160a01b0319166001600160a01b0392909216919091179055565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611c035760405162461bcd60e51b81526004016109179190612d55565b5060196110b88282613295565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611c595760405162461bcd60e51b81526004016109179190612d55565b5060066110b88282613295565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611caf5760405162461bcd60e51b81526004016109179190612d55565b50601b6110b88282613295565b600a6020526000908152604090208054600182015460028301805492939192611ce4906131e3565b80601f0160208091040260200160405190810160405280929190818152602001828054611d10906131e3565b8015611d5d5780601f10611d3257610100808354040283529160200191611d5d565b820191906000526020600020905b815481529060010190602001808311611d4057829003601f168201915b5050505050905083565b60028054610b65906131e3565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611dbd5760405162461bcd60e51b81526004016109179190612d55565b50601c6110b88282613295565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611e135760405162461bcd60e51b81526004016109179190612d55565b5060098054911515600160a01b0260ff60a01b19909216919091179055565b600081611e3e33611b33565b10156040518060400160405280600681526020016531323034303160d01b81525090611e7d5760405162461bcd60e51b81526004016109179190612d55565b506009546040805180820190915260068152651899181a181960d11b602082015290600160a01b900460ff161515600114611ecb5760405162461bcd60e51b81526004016109179190612d55565b506060833b15611ee857611ee084848361292f565b915050610de3565b611ee0848483612a4a565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611f3c5760405162461bcd60e51b81526004016109179190612d55565b50601a6110b88282613295565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611f925760405162461bcd60e51b81526004016109179190612d55565b5060056110b88282613295565b6001600160a01b039182166000908152600e6020908152604080832093909416825291909152205490565b81611fd53386611f9f565b101561200f57604080518082018252600681526518991818981960d11b6020820152905162461bcd60e51b81526109179190600401612d55565b61201d82610f203387611f9f565b336000908152600e602090815260408083206001600160a01b038916845290915290205561204e82610f4c85611b33565b6001600160a01b038085166000908152600860205260409081902092909255905133918616907f7a1a1088c929a111dda2dc0ca1cc650aa78525d11fd3089abf20c8474f5d82cc906120a59087908790879061321d565b60405180910390a350505050565b816120bd33611b33565b10156120f757604080518082018252600681526518991818181960d11b6020820152905162461bcd60e51b81526109179190600401612d55565b61210482610f2033611b33565b33600081815260086020526040902091909155612128908390610f4c908690611f9f565b6001600160a01b0384166000818152600e602090815260408083203380855292529182902093909355519091907ecd77abc69e7bbb6de9df8cbfcca8720df3a30decf9eefd187e72ab2ea2f5139061218390869086906133af565b60405180910390a3505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146121d95760405162461bcd60e51b81526004016109179190612d55565b506009805460ff60a81b1916600160a81b831515908102919091179091556040517fa0c691180b8089c0c84e478ee67d6325768666cd889f13de016771c6f7af1f8890600090a250565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461226c5760405162461bcd60e51b81526004016109179190612d55565b50816122788686611f9f565b10156122b257604080518082018252600681526531323132303160d01b6020820152905162461bcd60e51b81526109179190600401612d55565b6122c082610f208787611f9f565b6001600160a01b038087166000908152600e60209081526040808320938916835292905220556122f382610f4c85611b33565b60086000856001600160a01b03166001600160a01b0316815260200190815260200160002081905550846001600160a01b0316846001600160a01b03167f7a1a1088c929a111dda2dc0ca1cc650aa78525d11fd3089abf20c8474f5d82cc8585856040516123639392919061321d565b60405180910390a35050505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146123bb5760405162461bcd60e51b81526004016109179190612d55565b506018805460ff191660011790556040517f96151d7f1d8c50be29a45c0e3ae9ce2008888d1615b196e8f5ffd8c178e6dde890600090a1565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461243d5760405162461bcd60e51b81526004016109179190612d55565b506001600160a01b038216156124db57806124588385611f9f565b101561249257604080518082018252600681526531323131303160d01b6020820152905162461bcd60e51b81526109179190600401612d55565b6124a081610f208486611f9f565b6001600160a01b038084166000908152600e60209081526040808320938816835292905220556003546124d39082612bf2565b600355612566565b6001600160a01b03831660009081526008602052604090205481111561252f57604080518082018252600681526518991898981960d11b6020820152905162461bcd60e51b81526109179190600401612d55565b61253c81610f2085611b33565b6001600160a01b0384166000908152600860205260409020556003546125629082612bf2565b6003555b816001600160a01b0316836001600160a01b0316336001600160a01b03167fee02732fab40ece8284c756220846dff4b8d32058b86b35b4f0459bf172fcef0846040516125b591815260200190565b60405180910390a4505050565b601c8054610b65906131e3565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146126185760405162461bcd60e51b81526004016109179190612d55565b50600f8190556040518181527f82b19c9a00131a87eeff1903fcb9e4f2a3ba76dd86098586eea921a533e218dc90602001610e70565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146126975760405162461bcd60e51b81526004016109179190612d55565b5060408051808201909152600681526535303031303160d01b60208201526001600160a01b0382166126dc5760405162461bcd60e51b81526004016109179190612d55565b50600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60158054610b65906131e3565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461278e5760405162461bcd60e51b81526004016109179190612d55565b50600980546001600160a01b0319166001600160a01b0392909216919091179055565b60148054610b65906131e3565b600c81815481106127ce57600080fd5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509116919060ff1684565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146128505760405162461bcd60e51b81526004016109179190612d55565b506001600160a01b038216156128a95761286e81610f4c8486611f9f565b6001600160a01b038084166000908152600e60209081526040808320938816835292905220556003546128a19082612c05565b6003556128e0565b6128b681610f4c85611b33565b6001600160a01b0384166000908152600860205260409020556003546128dc9082612c05565b6003555b816001600160a01b0316836001600160a01b0316336001600160a01b03167f65adeb76912378393e600cb6f64f3310842a42e1eae86273dc775d0c47a0f2dc846040516125b591815260200190565b60045460408051808201909152600681526531323033303160d01b60208201526000916001600160a01b0386811691161461297d5760405162461bcd60e51b81526004016109179190612d55565b5061298b83610f2033611b33565b336000908152600860205260409020556129a883610f4c86611b33565b6001600160a01b0385166000818152600860205260409081902092909255905163607705c560e11b815285919063c0ee0b8a906129ed9033908890889060040161321d565b600060405180830381600087803b158015612a0757600080fd5b505af1158015612a1b573d6000803e3d6000fd5b50506040518681526001600160a01b03881692503391506000805160206133c98339815191529060200161104f565b6004546000906001600160a01b03163314801590612a6f5750600b5460ff1615156001145b15612aa857604080518082018252600681526531323032303160d01b6020820152905162461bcd60e51b81526109179190600401612d55565b6000546001600160a01b03858116911614612b775760095460005460405163d3da927f60e01b81526001600160a01b038781166004830152918216602482015291169063d3da927f90604401602060405180830381865afa158015612b11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b359190613355565b60408051808201909152600681526518991819181960d11b6020820152901515600114612b755760405162461bcd60e51b81526004016109179190612d55565b505b612b8483610f2033611b33565b33600090815260086020526040902055612ba183610f4c86611b33565b6001600160a01b0385166000818152600860205260409081902092909255905133906000805160206133c983398151915290612be09087815260200190565b60405180910390a35060019392505050565b6000612bfe82846131a4565b9392505050565b6000612bfe8284613191565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612c5057612c50612c11565b604052919050565b600082601f830112612c6957600080fd5b813567ffffffffffffffff811115612c8357612c83612c11565b612c96601f8201601f1916602001612c27565b818152846020838601011115612cab57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215612cdb57600080fd5b82359150602083013567ffffffffffffffff811115612cf957600080fd5b612d0585828601612c58565b9150509250929050565b6000815180845260005b81811015612d3557602081850181015186830182015201612d19565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000612bfe6020830184612d0f565b600067ffffffffffffffff821115612d8257612d82612c11565b5060051b60200190565b80356001600160a01b0381168114612da357600080fd5b919050565b600082601f830112612db957600080fd5b81356020612dce612dc983612d68565b612c27565b8083825260208201915060208460051b870101935086841115612df057600080fd5b602086015b84811015612e0c5780358352918301918301612df5565b509695505050505050565b60008060408385031215612e2a57600080fd5b823567ffffffffffffffff80821115612e4257600080fd5b818501915085601f830112612e5657600080fd5b81356020612e66612dc983612d68565b82815260059290921b84018101918181019089841115612e8557600080fd5b948201945b83861015612eaa57612e9b86612d8c565b82529482019490820190612e8a565b96505086013592505080821115612ec057600080fd5b50612d0585828601612da8565b8015158114612edb57600080fd5b50565b600060208284031215612ef057600080fd5b8135612bfe81612ecd565b600080600060608486031215612f1057600080fd5b612f1984612d8c565b9250612f2760208501612d8c565b9150604084013590509250925092565b600060208284031215612f4957600080fd5b813567ffffffffffffffff811115612f6057600080fd5b612f6c84828501612c58565b949350505050565b600060208284031215612f8657600080fd5b612bfe82612d8c565b600060208284031215612fa157600080fd5b5035919050565b60008060408385031215612fbb57600080fd5b612fc483612d8c565b946020939093013593505050565b600080600060608486031215612fe757600080fd5b612ff084612d8c565b925060208401359150604084013567ffffffffffffffff81111561301357600080fd5b61301f86828701612c58565b9150509250925092565b8381528260208201526060604082015260006130486060830184612d0f565b95945050505050565b6000806040838503121561306457600080fd5b61306d83612d8c565b915061307b60208401612d8c565b90509250929050565b6000806000806080858703121561309a57600080fd5b6130a385612d8c565b93506130b160208601612d8c565b925060408501359150606085013567ffffffffffffffff8111156130d457600080fd5b6130e087828801612c58565b91505092959194509250565b600080600080600060a0868803121561310457600080fd5b61310d86612d8c565b945061311b60208701612d8c565b935061312960408701612d8c565b925060608601359150608086013567ffffffffffffffff81111561314c57600080fd5b61315888828901612c58565b9150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610de357610de361317b565b81810381811115610de357610de361317b565b6001600160a01b0384811682528316602082015260606040820181905260009061304890830184612d0f565b600181811c908216806131f757607f821691505b60208210810361321757634e487b7160e01b600052602260045260246000fd5b50919050565b60018060a01b03841681528260208201526060604082015260006130486060830184612d0f565b601f821115613290576000816000526020600020601f850160051c8101602086101561326d5750805b601f850160051c820191505b8181101561328c57828155600101613279565b5050505b505050565b815167ffffffffffffffff8111156132af576132af612c11565b6132c3816132bd84546131e3565b84613244565b602080601f8311600181146132f857600084156132e05750858301515b600019600386901b1c1916600185901b17855561328c565b600085815260208120601f198616915b8281101561332757888601518255948401946001909101908401613308565b50858210156133455787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006020828403121561336757600080fd5b8151612bfe81612ecd565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906133a590830184612d0f565b9695505050505050565b828152604060208201526000612f6c6040830184612d0f56feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122088f29532258abd280c78b38a51851d03be753cbc68978a3c5f7fbc262f37bfa964736f6c63430008170033"
+ "bytecode": "60806040523480156200001157600080fd5b5060405162003a1f38038062003a1f8339810160408190526200003491620001f5565b600080546001600160a01b0319908116339182161717905560016200005a8c8262000431565b506002620000698b8262000431565b506003899055600f889055601962000082888262000431565b50601262000091878262000431565b506013859055601b620000a5858262000431565b506014620000b4848262000431565b506015620000c3838262000431565b506016620000d2828262000431565b5050600354600080546001600160a01b031681526008602052604090205550506018805460ff1990811690915560078054909116600117905550506009805460ff60a01b1916600160a01b17905550620004fd945050505050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200015557600080fd5b81516001600160401b03808211156200017257620001726200012d565b604051601f8301601f19908116603f011681019082821181831017156200019d576200019d6200012d565b8160405283815260209250866020858801011115620001bb57600080fd5b600091505b83821015620001df5785820183015181830184015290820190620001c0565b6000602085830101528094505050505092915050565b60008060008060008060008060008060006101608c8e0312156200021857600080fd5b8b516001600160401b038111156200022f57600080fd5b6200023d8e828f0162000143565b60208e0151909c5090506001600160401b038111156200025c57600080fd5b6200026a8e828f0162000143565b9a505060408c0151985060608c0151975060808c015160018060401b038111156200029457600080fd5b620002a28e828f0162000143565b60a08e015190985090506001600160401b03811115620002c157600080fd5b620002cf8e828f0162000143565b60c08e015160e08f0151919850965090506001600160401b03811115620002f557600080fd5b620003038e828f0162000143565b6101008e015190955090506001600160401b038111156200032357600080fd5b620003318e828f0162000143565b6101208e015190945090506001600160401b038111156200035157600080fd5b6200035f8e828f0162000143565b6101408e015190935090506001600160401b038111156200037f57600080fd5b6200038d8e828f0162000143565b9150509295989b509295989b9093969950565b600181811c90821680620003b557607f821691505b602082108103620003d657634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200042c576000816000526020600020601f850160051c81016020861015620004075750805b601f850160051c820191505b81811015620004285782815560010162000413565b5050505b505050565b81516001600160401b038111156200044d576200044d6200012d565b62000465816200045e8454620003a0565b84620003dc565b602080601f8311600181146200049d5760008415620004845750858301515b600019600386901b1c1916600185901b17855562000428565b600085815260208120601f198616915b82811015620004ce57888601518255948401946001909101908401620004ad565b5085821015620004ed5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b613512806200050d6000396000f3fe608060405234801561001057600080fd5b50600436106103f15760003560e01c80637c3a00fd11610215578063c267ce5f11610125578063ef8032ef116100b8578063fc590d0911610087578063fc590d0914610849578063fd0e856914610851578063fd14a22214610865578063fef1b9c014610878578063ff12dcea146108b857600080fd5b8063ef8032ef14610808578063f2fde38b1461081b578063f35eeaef1461082e578063f7502a7c1461083657600080fd5b8063db20266f116100f4578063db20266f146107b9578063e7464db1146107e4578063ed62c2a0146107f7578063ef4474cd146107ff57600080fd5b8063c267ce5f14610778578063c7109ec91461078b578063ca5cbbb51461079e578063d5d9d0c7146107b157600080fd5b806395d89b41116101a8578063ab62f92e11610177578063ab62f92e14610718578063b2a90a601461072b578063b967a52e1461073f578063b9b3e06a14610752578063bfe30fb01461076557600080fd5b806395d89b41146106d757806397e4c513146106df5780639cd23707146106f2578063a9059cbb1461070557600080fd5b80638ed8a9bc116101e45780638ed8a9bc1461067b578063919fe52d1461068e57806392ff0d31146106a15780639301a78b146106b557600080fd5b80637c3a00fd1461062c57806381ebdd79146106355780638ac08bf1146106555780638da5cb5b1461066857600080fd5b80633a2b6939116103105780635c40f6f4116102a35780636666e49c116102725780636666e49c146105e95780636f3b993f146105f157806370740aab146105fe57806370a082311461060657806376fa7a311461061957600080fd5b80635c40f6f41461059d5780635ccef3e7146105b05780635f84f302146105c357806363783444146105d657600080fd5b8063428630f6116102df578063428630f61461057c57806344fd9caa1461058457806358c3b8701461058d57806359d936171461059557600080fd5b80633a2b69391461053b5780633b18b9841461054357806340615cf81461055657806340eba90e1461056957600080fd5b806323b872dd116103885780632e0ad004116103575780632e0ad0041461051057806331cef44714610518578063329dbddc1461052b57806336f7ab5e1461053357600080fd5b806323b872dd146104b757806325287d42146104ca57806325d60861146104dd57806327e235e3146104f057600080fd5b8063153a1f3e116103c4578063153a1f3e1461046d57806318160ddd146104805780631935a88014610497578063200d2ed2146104aa57600080fd5b8063034f6b21146103f657806306eaa0b71461041857806306fdde031461042d5780630af7eb0f14610442575b600080fd5b6018546104039060ff1681565b60405190151581526020015b60405180910390f35b61042b610426366004612dbc565b6108cb565b005b610435610b95565b60405161040f9190612e49565b600954610455906001600160a01b031681565b6040516001600160a01b03909116815260200161040f565b61040361047b366004612f0b565b610c23565b61048960035481565b60405190815260200161040f565b61042b6104a5366004612fd2565b610e26565b6007546104039060ff1681565b6104036104c5366004612fef565b610eb8565b600454610455906001600160a01b031681565b61042b6104eb36600461302b565b61109f565b6104896104fe366004613068565b60086020526000908152604090205481565b6104356110f9565b61042b610526366004612dbc565b611106565b610435611281565b61043561128e565b61043561129b565b61042b610551366004613083565b6112a8565b61042b61056436600461309c565b611327565b61042b6105773660046130c6565b6113c5565b6104356116ac565b610489600f5481565b6104356116b9565b6104356116c6565b61042b6105ab366004612fd2565b6116d3565b61042b6105be366004612dbc565b611762565b61042b6105d1366004613083565b611ae4565b61042b6105e436600461302b565b611b33565b610435611b89565b600b546104039060ff1681565b610435611b96565b610489610614366004613068565b611ba3565b61042b610627366004613068565b611bbe565b61048960105481565b610489610643366004613068565b600d6020526000908152604090205481565b61042b61066336600461302b565b611c2a565b600054610455906001600160a01b031681565b61042b61068936600461302b565b611c80565b61042b61069c36600461302b565b611cd6565b60095461040390600160a81b900460ff1681565b6106c86106c3366004613068565b611d2c565b60405161040f9392919061311d565b610435611dd7565b61042b6106ed36600461302b565b611de4565b61042b610700366004612fd2565b611e3a565b61040361071336600461309c565b611ea2565b61042b61072636600461302b565b611f63565b60095461040390600160b01b900460ff1681565b61042b61074d36600461302b565b611fb9565b610489610760366004613145565b61200f565b61042b610773366004613178565b61203a565b61042b6107863660046130c6565b612123565b61042b610799366004612fd2565b612200565b61042b6107ac3660046131e0565b612293565b61042b6123e2565b6104896107c7366004613145565b600e60209081526000928352604080842090915290825290205481565b61042b6107f2366004612fef565b612464565b610435612632565b61048960135481565b61042b610816366004613083565b61263f565b61042b610829366004613068565b6126be565b6104356127a8565b61042b610844366004613068565b6127b5565b610435612821565b60095461040390600160a01b900460ff1681565b61042b610873366004612fd2565b61282e565b61088b610886366004613083565b612896565b604080516001600160a01b039586168152949093166020850152918301521515606082015260800161040f565b61042b6108c6366004612fef565b6128df565b336001600160a01b0316600c83815481106108e8576108e8613259565b60009182526020909120600490910201546001600160a01b03161480159061091b57506000546001600160a01b03163314155b1561095d57604080518082018252600681526531323038303160d01b6020820152905162461bcd60e51b81526109549190600401612e49565b60405180910390fd5b600c828154811061097057610970613259565b6000918252602082206003600490920201015460ff16151590036109c25760408051808201825260068152651899181c181960d11b6020820152905162461bcd60e51b81526109549190600401612e49565b600c82815481106109d5576109d5613259565b90600052602060002090600402016002015460086000600c85815481106109fe576109fe613259565b600091825260208083206004909202909101546001600160a01b0316835282019290925260400181208054909190610a37908490613285565b9091555050600c805483908110610a5057610a50613259565b906000526020600020906004020160020154600d6000600c8581548110610a7957610a79613259565b600091825260208083206004909202909101546001600160a01b0316835282019290925260400181208054909190610ab2908490613298565b925050819055506000600c8381548110610ace57610ace613259565b906000526020600020906004020160030160006101000a81548160ff021916908315150217905550817fa0cc3a4feb26502e6e6cd57b2113d58bdab80c6711d8252356be9a49945bb5f7600c8481548110610b2b57610b2b613259565b6000918252602090912060049091020154600c80546001600160a01b039092169186908110610b5c57610b5c613259565b6000918252602090912060016004909202010154604051610b8992916001600160a01b03169086906132ab565b60405180910390a25050565b60018054610ba2906132d7565b80601f0160208091040260200160405190810160405280929190818152602001828054610bce906132d7565b8015610c1b5780601f10610bf057610100808354040283529160200191610c1b565b820191906000526020600020905b815481529060010190602001808311610bfe57829003601f168201915b505050505081565b60008151835114610c6257604080518082018252600681526531323035303160d01b6020820152905162461bcd60e51b81526109549190600401612e49565b6000805b8451811015610c9e57838181518110610c8157610c81613259565b602002602001015182610c949190613285565b9150600101610c66565b5080610ca933611ba3565b1015610ce35760408051808201825260068152651899181a981960d11b6020820152905162461bcd60e51b81526109549190600401612e49565b6004546001600160a01b03163314610d445760095460408051808201909152600681526531323035303360d01b602082015290600160a81b900460ff161515600114610d425760405162461bcd60e51b81526004016109549190612e49565b505b606060006001935060005b8651811015610e1b57610d7b878281518110610d6d57610d6d613259565b60200260200101513b151590565b15610dc457610dbd878281518110610d9557610d95613259565b6020026020010151878381518110610daf57610daf613259565b602002602001015185612a07565b9150610e04565b610e01878281518110610dd957610dd9613259565b6020026020010151878381518110610df357610df3613259565b602002602001015185612b22565b91505b811515600003610e1357600094505b600101610d4f565b505050505b92915050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314610e6f5760405162461bcd60e51b81526004016109549190612e49565b50600b805460ff19168215159081179091556040519081527fe1455bc53682229469d6919bb96d7b338cbffea93170dfb5f02242c22fb6d07f906020015b60405180910390a150565b6000805460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314610f025760405162461bcd60e51b81526004016109549190612e49565b5081610f0d85611ba3565b1015610f4757604080518082018252600681526531323036303160d01b6020820152905162461bcd60e51b81526109549190600401612e49565b6060833b1561100c57610f6383610f5d87611ba3565b90612ce6565b6001600160a01b038616600090815260086020526040902055610f8f83610f8986611ba3565b90612cf9565b6001600160a01b0385166000818152600860205260409081902092909255905163607705c560e11b815285919063c0ee0b8a90610fd490339088908790600401613311565b600060405180830381600087803b158015610fee57600080fd5b505af1158015611002573d6000803e3d6000fd5b5050505050611059565b61101983610f5d87611ba3565b6001600160a01b03861660009081526008602052604090205561103f83610f8986611ba3565b6001600160a01b0385166000908152600860205260409020555b836001600160a01b0316856001600160a01b03166000805160206134bd8339815191528560405161108c91815260200190565b60405180910390a3506001949350505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146110e85760405162461bcd60e51b81526004016109549190612e49565b5060176110f58282613389565b5050565b601a8054610ba2906132d7565b60095460408051808201909152600681526531323130303160d01b602082015290600160b01b900460ff1615156001146111535760405162461bcd60e51b81526004016109549190612e49565b50600954600160a01b900460ff1615156001036112225760095460005460405163d3da927f60e01b81523360048201526001600160a01b03918216602482015291169063d3da927f90604401602060405180830381865afa1580156111bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e09190613449565b60408051808201909152600681526518991898181960d11b60208201529015156001146112205760405162461bcd60e51b81526004016109549190612e49565b505b336000908152600a602052604090208281556002016112418282613389565b507f3bb9553f633a7ecb4cbc5f9885e750a522496ce06deff1ed9184180ca83940c033838360405161127593929190613311565b60405180910390a15050565b60118054610ba2906132d7565b60058054610ba2906132d7565b60198054610ba2906132d7565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146112f15760405162461bcd60e51b81526004016109549190612e49565b5060138190556040518181527fe451abe602c33e612ea61221b5a142f7fe3c044286e42c8340ffe7fa86a5859790602001610ead565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146113705760405162461bcd60e51b81526004016109549190612e49565b506001600160a01b0382166000818152600a6020908152604091829020600101849055815192835282018390527fa42bd6bdfcb8f9b815c68e4ce0e16dec3f1e7ac53967ee8309653de522a735b19101611275565b600b5460ff1615806113e15750600954600160a81b900460ff16155b806113f35750816113f133611ba3565b105b1561142c57604080518082018252600681526531323037303160d01b6020820152905162461bcd60e51b81526109549190600401612e49565b6000546001600160a01b038481169116148015906114585750600954600160a01b900460ff1615156001145b156115175760095460005460405163d3da927f60e01b81526001600160a01b038681166004830152918216602482015291169063d3da927f90604401602060405180830381865afa1580156114b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d59190613449565b6040805180820190915260068152651899181b981960d11b60208201529015156001146115155760405162461bcd60e51b81526004016109549190612e49565b505b3360009081526008602052604081208054849290611536908490613298565b9091555050336000908152600d60205260408120805484929061155a908490613285565b9091555050600c805460408051608081018252338082526001600160a01b038881166020840190815283850189815260016060860181815290880189556000989098529351600487027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7810180549285166001600160a01b031993841617905591517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c8830180549190941691161790915591517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c983015593517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8ca909101805491151560ff1990921691909117905551909182917fa256c3bc72c26fbfd6285cfde8c7e345b4d0c7ccfc725d103e9f129c5d8a039a9161169e91889088908890613466565b60405180910390a250505050565b60068054610ba2906132d7565b60178054610ba2906132d7565b601b8054610ba2906132d7565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461171c5760405162461bcd60e51b81526004016109549190612e49565b506007805460ff191682151590811790915560405160ff9091161515907fe1e5c6f5867805bf3fab73f4df4b80d0e87e9262a7bc22ac7c2cb3fd5896222f90600090a250565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146117ab5760405162461bcd60e51b81526004016109549190612e49565b50600954600160a81b900460ff1615156000036117f657604080518082018252600681526531323039303160d01b6020820152905162461bcd60e51b81526109549190600401612e49565b600c828154811061180957611809613259565b6000918252602082206003600490920201015460ff161515900361185b5760408051808201825260068152651899181c981960d11b6020820152905162461bcd60e51b81526109549190600401612e49565b600c828154811061186e5761186e613259565b90600052602060002090600402016002015460086000600c858154811061189757611897613259565b60009182526020808320600160049093020191909101546001600160a01b03168352820192909252604001812080549091906118d4908490613285565b9091555050600c8054839081106118ed576118ed613259565b906000526020600020906004020160020154600d6000600c858154811061191657611916613259565b600091825260208083206004909202909101546001600160a01b031683528201929092526040018120805490919061194f908490613298565b925050819055506000600c838154811061196b5761196b613259565b906000526020600020906004020160030160006101000a81548160ff021916908315150217905550817f6b50d6e4941ce7ae74ed7f7f51df5fb7680754c2815a094c66bea5ca80a40eb1600c84815481106119c8576119c8613259565b6000918252602090912060049091020154600c80546001600160a01b0390921691869081106119f9576119f9613259565b6000918252602090912060016004909202010154604051611a2692916001600160a01b03169086906132ab565b60405180910390a2600c8281548110611a4157611a41613259565b6000918252602090912060016004909202010154600c80546001600160a01b039092169184908110611a7557611a75613259565b6000918252602090912060049091020154600c80546001600160a01b03909216916000805160206134bd833981519152919086908110611ab757611ab7613259565b906000526020600020906004020160020154604051611ad891815260200190565b60405180910390a35050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611b2d5760405162461bcd60e51b81526004016109549190612e49565b50601055565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611b7c5760405162461bcd60e51b81526004016109549190612e49565b5060116110f58282613389565b60128054610ba2906132d7565b60168054610ba2906132d7565b6001600160a01b031660009081526008602052604090205490565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611c075760405162461bcd60e51b81526004016109549190612e49565b50600480546001600160a01b0319166001600160a01b0392909216919091179055565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611c735760405162461bcd60e51b81526004016109549190612e49565b5060196110f58282613389565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611cc95760405162461bcd60e51b81526004016109549190612e49565b5060066110f58282613389565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611d1f5760405162461bcd60e51b81526004016109549190612e49565b50601b6110f58282613389565b600a6020526000908152604090208054600182015460028301805492939192611d54906132d7565b80601f0160208091040260200160405190810160405280929190818152602001828054611d80906132d7565b8015611dcd5780601f10611da257610100808354040283529160200191611dcd565b820191906000526020600020905b815481529060010190602001808311611db057829003601f168201915b5050505050905083565b60028054610ba2906132d7565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611e2d5760405162461bcd60e51b81526004016109549190612e49565b50601c6110f58282613389565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611e835760405162461bcd60e51b81526004016109549190612e49565b5060098054911515600160a81b0260ff60a81b19909216919091179055565b600081611eae33611ba3565b10156040518060400160405280600681526020016531323034303160d01b81525090611eed5760405162461bcd60e51b81526004016109549190612e49565b506009546040805180820190915260068152651899181a181960d11b602082015290600160a81b900460ff161515600114611f3b5760405162461bcd60e51b81526004016109549190612e49565b506060833b15611f5857611f50848483612a07565b915050610e20565b611f50848483612b22565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611fac5760405162461bcd60e51b81526004016109549190612e49565b50601a6110f58282613389565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146120025760405162461bcd60e51b81526004016109549190612e49565b5060056110f58282613389565b6001600160a01b039182166000908152600e6020908152604080832093909416825291909152205490565b81612045338661200f565b101561207f57604080518082018252600681526518991818981960d11b6020820152905162461bcd60e51b81526109549190600401612e49565b61208d82610f5d338761200f565b336000908152600e602090815260408083206001600160a01b03891684529091529020556120be82610f8985611ba3565b6001600160a01b038085166000908152600860205260409081902092909255905133918616907f7a1a1088c929a111dda2dc0ca1cc650aa78525d11fd3089abf20c8474f5d82cc9061211590879087908790613311565b60405180910390a350505050565b8161212d33611ba3565b101561216757604080518082018252600681526518991818181960d11b6020820152905162461bcd60e51b81526109549190600401612e49565b61217482610f5d33611ba3565b33600081815260086020526040902091909155612198908390610f8990869061200f565b6001600160a01b0384166000818152600e602090815260408083203380855292529182902093909355519091907ecd77abc69e7bbb6de9df8cbfcca8720df3a30decf9eefd187e72ab2ea2f513906121f390869086906134a3565b60405180910390a3505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146122495760405162461bcd60e51b81526004016109549190612e49565b506009805460ff60b01b1916600160b01b831515908102919091179091556040517fa0c691180b8089c0c84e478ee67d6325768666cd889f13de016771c6f7af1f8890600090a250565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146122dc5760405162461bcd60e51b81526004016109549190612e49565b50816122e8868661200f565b101561232257604080518082018252600681526531323132303160d01b6020820152905162461bcd60e51b81526109549190600401612e49565b61233082610f5d878761200f565b6001600160a01b038087166000908152600e602090815260408083209389168352929052205561236382610f8985611ba3565b60086000856001600160a01b03166001600160a01b0316815260200190815260200160002081905550846001600160a01b0316846001600160a01b03167f7a1a1088c929a111dda2dc0ca1cc650aa78525d11fd3089abf20c8474f5d82cc8585856040516123d393929190613311565b60405180910390a35050505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461242b5760405162461bcd60e51b81526004016109549190612e49565b506018805460ff191660011790556040517f96151d7f1d8c50be29a45c0e3ae9ce2008888d1615b196e8f5ffd8c178e6dde890600090a1565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146124ad5760405162461bcd60e51b81526004016109549190612e49565b506001600160a01b0382161561254b57806124c8838561200f565b101561250257604080518082018252600681526531323131303160d01b6020820152905162461bcd60e51b81526109549190600401612e49565b61251081610f5d848661200f565b6001600160a01b038084166000908152600e60209081526040808320938816835292905220556003546125439082612ce6565b6003556125d6565b6001600160a01b03831660009081526008602052604090205481111561259f57604080518082018252600681526518991898981960d11b6020820152905162461bcd60e51b81526109549190600401612e49565b6125ac81610f5d85611ba3565b6001600160a01b0384166000908152600860205260409020556003546125d29082612ce6565b6003555b816001600160a01b0316836001600160a01b0316336001600160a01b03167fee02732fab40ece8284c756220846dff4b8d32058b86b35b4f0459bf172fcef08460405161262591815260200190565b60405180910390a4505050565b601c8054610ba2906132d7565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146126885760405162461bcd60e51b81526004016109549190612e49565b50600f8190556040518181527f82b19c9a00131a87eeff1903fcb9e4f2a3ba76dd86098586eea921a533e218dc90602001610ead565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146127075760405162461bcd60e51b81526004016109549190612e49565b5060408051808201909152600681526535303031303160d01b60208201526001600160a01b03821661274c5760405162461bcd60e51b81526004016109549190612e49565b50600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60158054610ba2906132d7565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146127fe5760405162461bcd60e51b81526004016109549190612e49565b50600980546001600160a01b0319166001600160a01b0392909216919091179055565b60148054610ba2906132d7565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146128775760405162461bcd60e51b81526004016109549190612e49565b5060098054911515600160a01b0260ff60a01b19909216919091179055565b600c81815481106128a657600080fd5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509116919060ff1684565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146129285760405162461bcd60e51b81526004016109549190612e49565b506001600160a01b038216156129815761294681610f89848661200f565b6001600160a01b038084166000908152600e60209081526040808320938816835292905220556003546129799082612cf9565b6003556129b8565b61298e81610f8985611ba3565b6001600160a01b0384166000908152600860205260409020556003546129b49082612cf9565b6003555b816001600160a01b0316836001600160a01b0316336001600160a01b03167f65adeb76912378393e600cb6f64f3310842a42e1eae86273dc775d0c47a0f2dc8460405161262591815260200190565b60045460408051808201909152600681526531323033303160d01b60208201526000916001600160a01b03868116911614612a555760405162461bcd60e51b81526004016109549190612e49565b50612a6383610f5d33611ba3565b33600090815260086020526040902055612a8083610f8986611ba3565b6001600160a01b0385166000818152600860205260409081902092909255905163607705c560e11b815285919063c0ee0b8a90612ac590339088908890600401613311565b600060405180830381600087803b158015612adf57600080fd5b505af1158015612af3573d6000803e3d6000fd5b50506040518681526001600160a01b03881692503391506000805160206134bd8339815191529060200161108c565b6004546000906001600160a01b03163314801590612b475750600b5460ff1615156001145b15612b8057604080518082018252600681526531323032303160d01b6020820152905162461bcd60e51b81526109549190600401612e49565b6000546001600160a01b03858116911614801590612bac5750600954600160a01b900460ff1615156001145b15612c6b5760095460005460405163d3da927f60e01b81526001600160a01b038781166004830152918216602482015291169063d3da927f90604401602060405180830381865afa158015612c05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c299190613449565b60408051808201909152600681526518991819181960d11b6020820152901515600114612c695760405162461bcd60e51b81526004016109549190612e49565b505b612c7883610f5d33611ba3565b33600090815260086020526040902055612c9583610f8986611ba3565b6001600160a01b0385166000818152600860205260409081902092909255905133906000805160206134bd83398151915290612cd49087815260200190565b60405180910390a35060019392505050565b6000612cf28284613298565b9392505050565b6000612cf28284613285565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4457612d44612d05565b604052919050565b600082601f830112612d5d57600080fd5b813567ffffffffffffffff811115612d7757612d77612d05565b612d8a601f8201601f1916602001612d1b565b818152846020838601011115612d9f57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215612dcf57600080fd5b82359150602083013567ffffffffffffffff811115612ded57600080fd5b612df985828601612d4c565b9150509250929050565b6000815180845260005b81811015612e2957602081850181015186830182015201612e0d565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000612cf26020830184612e03565b600067ffffffffffffffff821115612e7657612e76612d05565b5060051b60200190565b80356001600160a01b0381168114612e9757600080fd5b919050565b600082601f830112612ead57600080fd5b81356020612ec2612ebd83612e5c565b612d1b565b8083825260208201915060208460051b870101935086841115612ee457600080fd5b602086015b84811015612f005780358352918301918301612ee9565b509695505050505050565b60008060408385031215612f1e57600080fd5b823567ffffffffffffffff80821115612f3657600080fd5b818501915085601f830112612f4a57600080fd5b81356020612f5a612ebd83612e5c565b82815260059290921b84018101918181019089841115612f7957600080fd5b948201945b83861015612f9e57612f8f86612e80565b82529482019490820190612f7e565b96505086013592505080821115612fb457600080fd5b50612df985828601612e9c565b8015158114612fcf57600080fd5b50565b600060208284031215612fe457600080fd5b8135612cf281612fc1565b60008060006060848603121561300457600080fd5b61300d84612e80565b925061301b60208501612e80565b9150604084013590509250925092565b60006020828403121561303d57600080fd5b813567ffffffffffffffff81111561305457600080fd5b61306084828501612d4c565b949350505050565b60006020828403121561307a57600080fd5b612cf282612e80565b60006020828403121561309557600080fd5b5035919050565b600080604083850312156130af57600080fd5b6130b883612e80565b946020939093013593505050565b6000806000606084860312156130db57600080fd5b6130e484612e80565b925060208401359150604084013567ffffffffffffffff81111561310757600080fd5b61311386828701612d4c565b9150509250925092565b83815282602082015260606040820152600061313c6060830184612e03565b95945050505050565b6000806040838503121561315857600080fd5b61316183612e80565b915061316f60208401612e80565b90509250929050565b6000806000806080858703121561318e57600080fd5b61319785612e80565b93506131a560208601612e80565b925060408501359150606085013567ffffffffffffffff8111156131c857600080fd5b6131d487828801612d4c565b91505092959194509250565b600080600080600060a086880312156131f857600080fd5b61320186612e80565b945061320f60208701612e80565b935061321d60408701612e80565b925060608601359150608086013567ffffffffffffffff81111561324057600080fd5b61324c88828901612d4c565b9150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610e2057610e2061326f565b81810381811115610e2057610e2061326f565b6001600160a01b0384811682528316602082015260606040820181905260009061313c90830184612e03565b600181811c908216806132eb57607f821691505b60208210810361330b57634e487b7160e01b600052602260045260246000fd5b50919050565b60018060a01b038416815282602082015260606040820152600061313c6060830184612e03565b601f821115613384576000816000526020600020601f850160051c810160208610156133615750805b601f850160051c820191505b818110156133805782815560010161336d565b5050505b505050565b815167ffffffffffffffff8111156133a3576133a3612d05565b6133b7816133b184546132d7565b84613338565b602080601f8311600181146133ec57600084156133d45750858301515b600019600386901b1c1916600185901b178555613380565b600085815260208120601f198616915b8281101561341b578886015182559484019460019091019084016133fc565b50858210156134395787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006020828403121561345b57600080fd5b8151612cf281612fc1565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061349990830184612e03565b9695505050505050565b8281526040602082015260006130606040830184612e0356feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122058ccc1e9b73794228a24d20df37b2c765313479f9d25721169fb5f5a2203353764736f6c63430008170033",
+ "deployedBytecode": "608060405234801561001057600080fd5b50600436106103f15760003560e01c80637c3a00fd11610215578063c267ce5f11610125578063ef8032ef116100b8578063fc590d0911610087578063fc590d0914610849578063fd0e856914610851578063fd14a22214610865578063fef1b9c014610878578063ff12dcea146108b857600080fd5b8063ef8032ef14610808578063f2fde38b1461081b578063f35eeaef1461082e578063f7502a7c1461083657600080fd5b8063db20266f116100f4578063db20266f146107b9578063e7464db1146107e4578063ed62c2a0146107f7578063ef4474cd146107ff57600080fd5b8063c267ce5f14610778578063c7109ec91461078b578063ca5cbbb51461079e578063d5d9d0c7146107b157600080fd5b806395d89b41116101a8578063ab62f92e11610177578063ab62f92e14610718578063b2a90a601461072b578063b967a52e1461073f578063b9b3e06a14610752578063bfe30fb01461076557600080fd5b806395d89b41146106d757806397e4c513146106df5780639cd23707146106f2578063a9059cbb1461070557600080fd5b80638ed8a9bc116101e45780638ed8a9bc1461067b578063919fe52d1461068e57806392ff0d31146106a15780639301a78b146106b557600080fd5b80637c3a00fd1461062c57806381ebdd79146106355780638ac08bf1146106555780638da5cb5b1461066857600080fd5b80633a2b6939116103105780635c40f6f4116102a35780636666e49c116102725780636666e49c146105e95780636f3b993f146105f157806370740aab146105fe57806370a082311461060657806376fa7a311461061957600080fd5b80635c40f6f41461059d5780635ccef3e7146105b05780635f84f302146105c357806363783444146105d657600080fd5b8063428630f6116102df578063428630f61461057c57806344fd9caa1461058457806358c3b8701461058d57806359d936171461059557600080fd5b80633a2b69391461053b5780633b18b9841461054357806340615cf81461055657806340eba90e1461056957600080fd5b806323b872dd116103885780632e0ad004116103575780632e0ad0041461051057806331cef44714610518578063329dbddc1461052b57806336f7ab5e1461053357600080fd5b806323b872dd146104b757806325287d42146104ca57806325d60861146104dd57806327e235e3146104f057600080fd5b8063153a1f3e116103c4578063153a1f3e1461046d57806318160ddd146104805780631935a88014610497578063200d2ed2146104aa57600080fd5b8063034f6b21146103f657806306eaa0b71461041857806306fdde031461042d5780630af7eb0f14610442575b600080fd5b6018546104039060ff1681565b60405190151581526020015b60405180910390f35b61042b610426366004612dbc565b6108cb565b005b610435610b95565b60405161040f9190612e49565b600954610455906001600160a01b031681565b6040516001600160a01b03909116815260200161040f565b61040361047b366004612f0b565b610c23565b61048960035481565b60405190815260200161040f565b61042b6104a5366004612fd2565b610e26565b6007546104039060ff1681565b6104036104c5366004612fef565b610eb8565b600454610455906001600160a01b031681565b61042b6104eb36600461302b565b61109f565b6104896104fe366004613068565b60086020526000908152604090205481565b6104356110f9565b61042b610526366004612dbc565b611106565b610435611281565b61043561128e565b61043561129b565b61042b610551366004613083565b6112a8565b61042b61056436600461309c565b611327565b61042b6105773660046130c6565b6113c5565b6104356116ac565b610489600f5481565b6104356116b9565b6104356116c6565b61042b6105ab366004612fd2565b6116d3565b61042b6105be366004612dbc565b611762565b61042b6105d1366004613083565b611ae4565b61042b6105e436600461302b565b611b33565b610435611b89565b600b546104039060ff1681565b610435611b96565b610489610614366004613068565b611ba3565b61042b610627366004613068565b611bbe565b61048960105481565b610489610643366004613068565b600d6020526000908152604090205481565b61042b61066336600461302b565b611c2a565b600054610455906001600160a01b031681565b61042b61068936600461302b565b611c80565b61042b61069c36600461302b565b611cd6565b60095461040390600160a81b900460ff1681565b6106c86106c3366004613068565b611d2c565b60405161040f9392919061311d565b610435611dd7565b61042b6106ed36600461302b565b611de4565b61042b610700366004612fd2565b611e3a565b61040361071336600461309c565b611ea2565b61042b61072636600461302b565b611f63565b60095461040390600160b01b900460ff1681565b61042b61074d36600461302b565b611fb9565b610489610760366004613145565b61200f565b61042b610773366004613178565b61203a565b61042b6107863660046130c6565b612123565b61042b610799366004612fd2565b612200565b61042b6107ac3660046131e0565b612293565b61042b6123e2565b6104896107c7366004613145565b600e60209081526000928352604080842090915290825290205481565b61042b6107f2366004612fef565b612464565b610435612632565b61048960135481565b61042b610816366004613083565b61263f565b61042b610829366004613068565b6126be565b6104356127a8565b61042b610844366004613068565b6127b5565b610435612821565b60095461040390600160a01b900460ff1681565b61042b610873366004612fd2565b61282e565b61088b610886366004613083565b612896565b604080516001600160a01b039586168152949093166020850152918301521515606082015260800161040f565b61042b6108c6366004612fef565b6128df565b336001600160a01b0316600c83815481106108e8576108e8613259565b60009182526020909120600490910201546001600160a01b03161480159061091b57506000546001600160a01b03163314155b1561095d57604080518082018252600681526531323038303160d01b6020820152905162461bcd60e51b81526109549190600401612e49565b60405180910390fd5b600c828154811061097057610970613259565b6000918252602082206003600490920201015460ff16151590036109c25760408051808201825260068152651899181c181960d11b6020820152905162461bcd60e51b81526109549190600401612e49565b600c82815481106109d5576109d5613259565b90600052602060002090600402016002015460086000600c85815481106109fe576109fe613259565b600091825260208083206004909202909101546001600160a01b0316835282019290925260400181208054909190610a37908490613285565b9091555050600c805483908110610a5057610a50613259565b906000526020600020906004020160020154600d6000600c8581548110610a7957610a79613259565b600091825260208083206004909202909101546001600160a01b0316835282019290925260400181208054909190610ab2908490613298565b925050819055506000600c8381548110610ace57610ace613259565b906000526020600020906004020160030160006101000a81548160ff021916908315150217905550817fa0cc3a4feb26502e6e6cd57b2113d58bdab80c6711d8252356be9a49945bb5f7600c8481548110610b2b57610b2b613259565b6000918252602090912060049091020154600c80546001600160a01b039092169186908110610b5c57610b5c613259565b6000918252602090912060016004909202010154604051610b8992916001600160a01b03169086906132ab565b60405180910390a25050565b60018054610ba2906132d7565b80601f0160208091040260200160405190810160405280929190818152602001828054610bce906132d7565b8015610c1b5780601f10610bf057610100808354040283529160200191610c1b565b820191906000526020600020905b815481529060010190602001808311610bfe57829003601f168201915b505050505081565b60008151835114610c6257604080518082018252600681526531323035303160d01b6020820152905162461bcd60e51b81526109549190600401612e49565b6000805b8451811015610c9e57838181518110610c8157610c81613259565b602002602001015182610c949190613285565b9150600101610c66565b5080610ca933611ba3565b1015610ce35760408051808201825260068152651899181a981960d11b6020820152905162461bcd60e51b81526109549190600401612e49565b6004546001600160a01b03163314610d445760095460408051808201909152600681526531323035303360d01b602082015290600160a81b900460ff161515600114610d425760405162461bcd60e51b81526004016109549190612e49565b505b606060006001935060005b8651811015610e1b57610d7b878281518110610d6d57610d6d613259565b60200260200101513b151590565b15610dc457610dbd878281518110610d9557610d95613259565b6020026020010151878381518110610daf57610daf613259565b602002602001015185612a07565b9150610e04565b610e01878281518110610dd957610dd9613259565b6020026020010151878381518110610df357610df3613259565b602002602001015185612b22565b91505b811515600003610e1357600094505b600101610d4f565b505050505b92915050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314610e6f5760405162461bcd60e51b81526004016109549190612e49565b50600b805460ff19168215159081179091556040519081527fe1455bc53682229469d6919bb96d7b338cbffea93170dfb5f02242c22fb6d07f906020015b60405180910390a150565b6000805460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314610f025760405162461bcd60e51b81526004016109549190612e49565b5081610f0d85611ba3565b1015610f4757604080518082018252600681526531323036303160d01b6020820152905162461bcd60e51b81526109549190600401612e49565b6060833b1561100c57610f6383610f5d87611ba3565b90612ce6565b6001600160a01b038616600090815260086020526040902055610f8f83610f8986611ba3565b90612cf9565b6001600160a01b0385166000818152600860205260409081902092909255905163607705c560e11b815285919063c0ee0b8a90610fd490339088908790600401613311565b600060405180830381600087803b158015610fee57600080fd5b505af1158015611002573d6000803e3d6000fd5b5050505050611059565b61101983610f5d87611ba3565b6001600160a01b03861660009081526008602052604090205561103f83610f8986611ba3565b6001600160a01b0385166000908152600860205260409020555b836001600160a01b0316856001600160a01b03166000805160206134bd8339815191528560405161108c91815260200190565b60405180910390a3506001949350505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146110e85760405162461bcd60e51b81526004016109549190612e49565b5060176110f58282613389565b5050565b601a8054610ba2906132d7565b60095460408051808201909152600681526531323130303160d01b602082015290600160b01b900460ff1615156001146111535760405162461bcd60e51b81526004016109549190612e49565b50600954600160a01b900460ff1615156001036112225760095460005460405163d3da927f60e01b81523360048201526001600160a01b03918216602482015291169063d3da927f90604401602060405180830381865afa1580156111bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e09190613449565b60408051808201909152600681526518991898181960d11b60208201529015156001146112205760405162461bcd60e51b81526004016109549190612e49565b505b336000908152600a602052604090208281556002016112418282613389565b507f3bb9553f633a7ecb4cbc5f9885e750a522496ce06deff1ed9184180ca83940c033838360405161127593929190613311565b60405180910390a15050565b60118054610ba2906132d7565b60058054610ba2906132d7565b60198054610ba2906132d7565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146112f15760405162461bcd60e51b81526004016109549190612e49565b5060138190556040518181527fe451abe602c33e612ea61221b5a142f7fe3c044286e42c8340ffe7fa86a5859790602001610ead565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146113705760405162461bcd60e51b81526004016109549190612e49565b506001600160a01b0382166000818152600a6020908152604091829020600101849055815192835282018390527fa42bd6bdfcb8f9b815c68e4ce0e16dec3f1e7ac53967ee8309653de522a735b19101611275565b600b5460ff1615806113e15750600954600160a81b900460ff16155b806113f35750816113f133611ba3565b105b1561142c57604080518082018252600681526531323037303160d01b6020820152905162461bcd60e51b81526109549190600401612e49565b6000546001600160a01b038481169116148015906114585750600954600160a01b900460ff1615156001145b156115175760095460005460405163d3da927f60e01b81526001600160a01b038681166004830152918216602482015291169063d3da927f90604401602060405180830381865afa1580156114b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d59190613449565b6040805180820190915260068152651899181b981960d11b60208201529015156001146115155760405162461bcd60e51b81526004016109549190612e49565b505b3360009081526008602052604081208054849290611536908490613298565b9091555050336000908152600d60205260408120805484929061155a908490613285565b9091555050600c805460408051608081018252338082526001600160a01b038881166020840190815283850189815260016060860181815290880189556000989098529351600487027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7810180549285166001600160a01b031993841617905591517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c8830180549190941691161790915591517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c983015593517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8ca909101805491151560ff1990921691909117905551909182917fa256c3bc72c26fbfd6285cfde8c7e345b4d0c7ccfc725d103e9f129c5d8a039a9161169e91889088908890613466565b60405180910390a250505050565b60068054610ba2906132d7565b60178054610ba2906132d7565b601b8054610ba2906132d7565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461171c5760405162461bcd60e51b81526004016109549190612e49565b506007805460ff191682151590811790915560405160ff9091161515907fe1e5c6f5867805bf3fab73f4df4b80d0e87e9262a7bc22ac7c2cb3fd5896222f90600090a250565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146117ab5760405162461bcd60e51b81526004016109549190612e49565b50600954600160a81b900460ff1615156000036117f657604080518082018252600681526531323039303160d01b6020820152905162461bcd60e51b81526109549190600401612e49565b600c828154811061180957611809613259565b6000918252602082206003600490920201015460ff161515900361185b5760408051808201825260068152651899181c981960d11b6020820152905162461bcd60e51b81526109549190600401612e49565b600c828154811061186e5761186e613259565b90600052602060002090600402016002015460086000600c858154811061189757611897613259565b60009182526020808320600160049093020191909101546001600160a01b03168352820192909252604001812080549091906118d4908490613285565b9091555050600c8054839081106118ed576118ed613259565b906000526020600020906004020160020154600d6000600c858154811061191657611916613259565b600091825260208083206004909202909101546001600160a01b031683528201929092526040018120805490919061194f908490613298565b925050819055506000600c838154811061196b5761196b613259565b906000526020600020906004020160030160006101000a81548160ff021916908315150217905550817f6b50d6e4941ce7ae74ed7f7f51df5fb7680754c2815a094c66bea5ca80a40eb1600c84815481106119c8576119c8613259565b6000918252602090912060049091020154600c80546001600160a01b0390921691869081106119f9576119f9613259565b6000918252602090912060016004909202010154604051611a2692916001600160a01b03169086906132ab565b60405180910390a2600c8281548110611a4157611a41613259565b6000918252602090912060016004909202010154600c80546001600160a01b039092169184908110611a7557611a75613259565b6000918252602090912060049091020154600c80546001600160a01b03909216916000805160206134bd833981519152919086908110611ab757611ab7613259565b906000526020600020906004020160020154604051611ad891815260200190565b60405180910390a35050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611b2d5760405162461bcd60e51b81526004016109549190612e49565b50601055565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611b7c5760405162461bcd60e51b81526004016109549190612e49565b5060116110f58282613389565b60128054610ba2906132d7565b60168054610ba2906132d7565b6001600160a01b031660009081526008602052604090205490565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611c075760405162461bcd60e51b81526004016109549190612e49565b50600480546001600160a01b0319166001600160a01b0392909216919091179055565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611c735760405162461bcd60e51b81526004016109549190612e49565b5060196110f58282613389565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611cc95760405162461bcd60e51b81526004016109549190612e49565b5060066110f58282613389565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611d1f5760405162461bcd60e51b81526004016109549190612e49565b50601b6110f58282613389565b600a6020526000908152604090208054600182015460028301805492939192611d54906132d7565b80601f0160208091040260200160405190810160405280929190818152602001828054611d80906132d7565b8015611dcd5780601f10611da257610100808354040283529160200191611dcd565b820191906000526020600020905b815481529060010190602001808311611db057829003601f168201915b5050505050905083565b60028054610ba2906132d7565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611e2d5760405162461bcd60e51b81526004016109549190612e49565b50601c6110f58282613389565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611e835760405162461bcd60e51b81526004016109549190612e49565b5060098054911515600160a81b0260ff60a81b19909216919091179055565b600081611eae33611ba3565b10156040518060400160405280600681526020016531323034303160d01b81525090611eed5760405162461bcd60e51b81526004016109549190612e49565b506009546040805180820190915260068152651899181a181960d11b602082015290600160a81b900460ff161515600114611f3b5760405162461bcd60e51b81526004016109549190612e49565b506060833b15611f5857611f50848483612a07565b915050610e20565b611f50848483612b22565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b03163314611fac5760405162461bcd60e51b81526004016109549190612e49565b50601a6110f58282613389565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146120025760405162461bcd60e51b81526004016109549190612e49565b5060056110f58282613389565b6001600160a01b039182166000908152600e6020908152604080832093909416825291909152205490565b81612045338661200f565b101561207f57604080518082018252600681526518991818981960d11b6020820152905162461bcd60e51b81526109549190600401612e49565b61208d82610f5d338761200f565b336000908152600e602090815260408083206001600160a01b03891684529091529020556120be82610f8985611ba3565b6001600160a01b038085166000908152600860205260409081902092909255905133918616907f7a1a1088c929a111dda2dc0ca1cc650aa78525d11fd3089abf20c8474f5d82cc9061211590879087908790613311565b60405180910390a350505050565b8161212d33611ba3565b101561216757604080518082018252600681526518991818181960d11b6020820152905162461bcd60e51b81526109549190600401612e49565b61217482610f5d33611ba3565b33600081815260086020526040902091909155612198908390610f8990869061200f565b6001600160a01b0384166000818152600e602090815260408083203380855292529182902093909355519091907ecd77abc69e7bbb6de9df8cbfcca8720df3a30decf9eefd187e72ab2ea2f513906121f390869086906134a3565b60405180910390a3505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146122495760405162461bcd60e51b81526004016109549190612e49565b506009805460ff60b01b1916600160b01b831515908102919091179091556040517fa0c691180b8089c0c84e478ee67d6325768666cd889f13de016771c6f7af1f8890600090a250565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146122dc5760405162461bcd60e51b81526004016109549190612e49565b50816122e8868661200f565b101561232257604080518082018252600681526531323132303160d01b6020820152905162461bcd60e51b81526109549190600401612e49565b61233082610f5d878761200f565b6001600160a01b038087166000908152600e602090815260408083209389168352929052205561236382610f8985611ba3565b60086000856001600160a01b03166001600160a01b0316815260200190815260200160002081905550846001600160a01b0316846001600160a01b03167f7a1a1088c929a111dda2dc0ca1cc650aa78525d11fd3089abf20c8474f5d82cc8585856040516123d393929190613311565b60405180910390a35050505050565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b0316331461242b5760405162461bcd60e51b81526004016109549190612e49565b506018805460ff191660011790556040517f96151d7f1d8c50be29a45c0e3ae9ce2008888d1615b196e8f5ffd8c178e6dde890600090a1565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146124ad5760405162461bcd60e51b81526004016109549190612e49565b506001600160a01b0382161561254b57806124c8838561200f565b101561250257604080518082018252600681526531323131303160d01b6020820152905162461bcd60e51b81526109549190600401612e49565b61251081610f5d848661200f565b6001600160a01b038084166000908152600e60209081526040808320938816835292905220556003546125439082612ce6565b6003556125d6565b6001600160a01b03831660009081526008602052604090205481111561259f57604080518082018252600681526518991898981960d11b6020820152905162461bcd60e51b81526109549190600401612e49565b6125ac81610f5d85611ba3565b6001600160a01b0384166000908152600860205260409020556003546125d29082612ce6565b6003555b816001600160a01b0316836001600160a01b0316336001600160a01b03167fee02732fab40ece8284c756220846dff4b8d32058b86b35b4f0459bf172fcef08460405161262591815260200190565b60405180910390a4505050565b601c8054610ba2906132d7565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146126885760405162461bcd60e51b81526004016109549190612e49565b50600f8190556040518181527f82b19c9a00131a87eeff1903fcb9e4f2a3ba76dd86098586eea921a533e218dc90602001610ead565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146127075760405162461bcd60e51b81526004016109549190612e49565b5060408051808201909152600681526535303031303160d01b60208201526001600160a01b03821661274c5760405162461bcd60e51b81526004016109549190612e49565b50600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60158054610ba2906132d7565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146127fe5760405162461bcd60e51b81526004016109549190612e49565b50600980546001600160a01b0319166001600160a01b0392909216919091179055565b60148054610ba2906132d7565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146128775760405162461bcd60e51b81526004016109549190612e49565b5060098054911515600160a01b0260ff60a01b19909216919091179055565b600c81815481106128a657600080fd5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509116919060ff1684565b60005460408051808201909152600681526535303030303160d01b6020820152906001600160a01b031633146129285760405162461bcd60e51b81526004016109549190612e49565b506001600160a01b038216156129815761294681610f89848661200f565b6001600160a01b038084166000908152600e60209081526040808320938816835292905220556003546129799082612cf9565b6003556129b8565b61298e81610f8985611ba3565b6001600160a01b0384166000908152600860205260409020556003546129b49082612cf9565b6003555b816001600160a01b0316836001600160a01b0316336001600160a01b03167f65adeb76912378393e600cb6f64f3310842a42e1eae86273dc775d0c47a0f2dc8460405161262591815260200190565b60045460408051808201909152600681526531323033303160d01b60208201526000916001600160a01b03868116911614612a555760405162461bcd60e51b81526004016109549190612e49565b50612a6383610f5d33611ba3565b33600090815260086020526040902055612a8083610f8986611ba3565b6001600160a01b0385166000818152600860205260409081902092909255905163607705c560e11b815285919063c0ee0b8a90612ac590339088908890600401613311565b600060405180830381600087803b158015612adf57600080fd5b505af1158015612af3573d6000803e3d6000fd5b50506040518681526001600160a01b03881692503391506000805160206134bd8339815191529060200161108c565b6004546000906001600160a01b03163314801590612b475750600b5460ff1615156001145b15612b8057604080518082018252600681526531323032303160d01b6020820152905162461bcd60e51b81526109549190600401612e49565b6000546001600160a01b03858116911614801590612bac5750600954600160a01b900460ff1615156001145b15612c6b5760095460005460405163d3da927f60e01b81526001600160a01b038781166004830152918216602482015291169063d3da927f90604401602060405180830381865afa158015612c05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c299190613449565b60408051808201909152600681526518991819181960d11b6020820152901515600114612c695760405162461bcd60e51b81526004016109549190612e49565b505b612c7883610f5d33611ba3565b33600090815260086020526040902055612c9583610f8986611ba3565b6001600160a01b0385166000818152600860205260409081902092909255905133906000805160206134bd83398151915290612cd49087815260200190565b60405180910390a35060019392505050565b6000612cf28284613298565b9392505050565b6000612cf28284613285565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4457612d44612d05565b604052919050565b600082601f830112612d5d57600080fd5b813567ffffffffffffffff811115612d7757612d77612d05565b612d8a601f8201601f1916602001612d1b565b818152846020838601011115612d9f57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215612dcf57600080fd5b82359150602083013567ffffffffffffffff811115612ded57600080fd5b612df985828601612d4c565b9150509250929050565b6000815180845260005b81811015612e2957602081850181015186830182015201612e0d565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000612cf26020830184612e03565b600067ffffffffffffffff821115612e7657612e76612d05565b5060051b60200190565b80356001600160a01b0381168114612e9757600080fd5b919050565b600082601f830112612ead57600080fd5b81356020612ec2612ebd83612e5c565b612d1b565b8083825260208201915060208460051b870101935086841115612ee457600080fd5b602086015b84811015612f005780358352918301918301612ee9565b509695505050505050565b60008060408385031215612f1e57600080fd5b823567ffffffffffffffff80821115612f3657600080fd5b818501915085601f830112612f4a57600080fd5b81356020612f5a612ebd83612e5c565b82815260059290921b84018101918181019089841115612f7957600080fd5b948201945b83861015612f9e57612f8f86612e80565b82529482019490820190612f7e565b96505086013592505080821115612fb457600080fd5b50612df985828601612e9c565b8015158114612fcf57600080fd5b50565b600060208284031215612fe457600080fd5b8135612cf281612fc1565b60008060006060848603121561300457600080fd5b61300d84612e80565b925061301b60208501612e80565b9150604084013590509250925092565b60006020828403121561303d57600080fd5b813567ffffffffffffffff81111561305457600080fd5b61306084828501612d4c565b949350505050565b60006020828403121561307a57600080fd5b612cf282612e80565b60006020828403121561309557600080fd5b5035919050565b600080604083850312156130af57600080fd5b6130b883612e80565b946020939093013593505050565b6000806000606084860312156130db57600080fd5b6130e484612e80565b925060208401359150604084013567ffffffffffffffff81111561310757600080fd5b61311386828701612d4c565b9150509250925092565b83815282602082015260606040820152600061313c6060830184612e03565b95945050505050565b6000806040838503121561315857600080fd5b61316183612e80565b915061316f60208401612e80565b90509250929050565b6000806000806080858703121561318e57600080fd5b61319785612e80565b93506131a560208601612e80565b925060408501359150606085013567ffffffffffffffff8111156131c857600080fd5b6131d487828801612d4c565b91505092959194509250565b600080600080600060a086880312156131f857600080fd5b61320186612e80565b945061320f60208701612e80565b935061321d60408701612e80565b925060608601359150608086013567ffffffffffffffff81111561324057600080fd5b61324c88828901612d4c565b9150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610e2057610e2061326f565b81810381811115610e2057610e2061326f565b6001600160a01b0384811682528316602082015260606040820181905260009061313c90830184612e03565b600181811c908216806132eb57607f821691505b60208210810361330b57634e487b7160e01b600052602260045260246000fd5b50919050565b60018060a01b038416815282602082015260606040820152600061313c6060830184612e03565b601f821115613384576000816000526020600020601f850160051c810160208610156133615750805b601f850160051c820191505b818110156133805782815560010161336d565b5050505b505050565b815167ffffffffffffffff8111156133a3576133a3612d05565b6133b7816133b184546132d7565b84613338565b602080601f8311600181146133ec57600084156133d45750858301515b600019600386901b1c1916600185901b178555613380565b600085815260208120601f198616915b8281101561341b578886015182559484019460019091019084016133fc565b50858210156134395787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006020828403121561345b57600080fd5b8151612cf281612fc1565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061349990830184612e03565b9695505050505050565b8281526040602082015260006130606040830184612e0356feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122058ccc1e9b73794228a24d20df37b2c765313479f9d25721169fb5f5a2203353764736f6c63430008170033"
}
\ No newline at end of file
diff --git a/contracts/contract_version.md b/contracts/contract_version.md
index bbf89d63..02046028 100644
--- a/contracts/contract_version.md
+++ b/contracts/contract_version.md
@@ -1,23 +1,25 @@
-| Contract json file | version | bytecode used | ABI used |
-|---------------------------------|--------------|-------------------------|----------|
-| ContractReceiver.json | **v22.12.0** | no | yes |
-| ContractRegistry.json | **v22.12.0** | no | yes |
-| E2EMessaging.json | **v22.12.0** | yes(only for unittest) | yes |
-| EscrowStorage.json | **v22.12.0** | yes(only for unittest) | yes |
-| ExchangeStorage.json | **v22.12.0** | yes(only for unittest) | yes |
-| IbetCoupon.json | **v22.12.0** | yes(only for unittest) | yes |
-| IbetEscrow.json | **v22.12.0** | yes(only for unittest) | yes |
-| IbetExchange.json | **v22.12.0** | yes(only for unittest) | yes |
-| IbetExchangeInterface.json | **v22.12.0** | no | yes |
-| IbetMembership.json | **v22.12.0** | yes(only for unittest) | yes |
-| IbetSecurityTokenEscrow.json | **v22.12.0** | yes(only for unittest) | yes |
-| IbetSecurityTokenInterface.json | **v22.12.0** | no | yes |
-| IbetShare.json | **v22.12.0** | **yes** | yes |
-| IbetStandardTokenInterface.json | **v22.12.0** | no | yes |
-| IbetStandardToken.json | **v22.12.0** | yes(only for unittest) | yes |
-| IbetStraightBond.json | **v23.12.0** | **yes** | yes |
-| Ownable.json | **v22.12.0** | yes(only for unittest) | yes |
-| PaymentGateway.json | **v22.12.0** | yes(only for unittest) | yes |
-| PersonalInfo.json | **v22.12.0** | yes(only for unittest) | yes |
-| TokenList.json | **v22.12.0** | yes(only for unittest) | yes |
-| FreezeLog.json | **v23.12.0** | yes(only for unittest) | yes |
\ No newline at end of file
+| Contract json file | version | bytecode used | ABI used |
+|---------------------------------|--------------|------------------------|----------|
+| Ownable.json | **v22.12.0** | yes(only for unittest) | yes |
+| ContractReceiver.json | **v22.12.0** | no | yes |
+| ContractRegistry.json | **v22.12.0** | no | yes |
+| TokenList.json | **v22.12.0** | yes(only for unittest) | yes |
+| IbetStandardTokenInterface.json | **v22.12.0** | no | yes |
+| IbetStandardToken.json | **v22.12.0** | yes(only for unittest) | yes |
+| IbetMembership.json | **v22.12.0** | yes(only for unittest) | yes |
+| IbetCoupon.json | **v22.12.0** | yes(only for unittest) | yes |
+| IbetSecurityTokenInterface.json | **v24.6.0** | no | yes |
+| IbetStraightBond.json | **v24.6.0** | **yes** | yes |
+| IbetShare.json | **v24.6.0** | **yes** | yes |
+| IbetExchangeInterface.json | **v22.12.0** | no | yes |
+| IbetExchange.json | **v22.12.0** | yes(only for unittest) | yes |
+| ExchangeStorage.json | **v22.12.0** | yes(only for unittest) | yes |
+| IbetEscrow.json | **v22.12.0** | yes(only for unittest) | yes |
+| EscrowStorage.json | **v22.12.0** | yes(only for unittest) | yes |
+| IbetSecurityTokenEscrow.json | **v22.12.0** | yes(only for unittest) | yes |
+| DVPStorage.json | **v24.6.0** | yes(only for unittest) | yes |
+| IbetSecurityTokenDVP.json | **v24.6.0** | yes(only for unittest) | yes |
+| PaymentGateway.json | **v22.12.0** | yes(only for unittest) | yes |
+| PersonalInfo.json | **v22.12.0** | yes(only for unittest) | yes |
+| FreezeLog.json | **v23.12.0** | yes(only for unittest) | yes |
+| E2EMessaging.json | **v22.12.0** | yes(only for unittest) | yes |
diff --git a/docker-compose.yml b/docker-compose.yml
index 80893f1b..204aaaa5 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,5 +1,3 @@
-version: "3"
-
services:
postgres:
image: postgres:15
@@ -9,28 +7,23 @@ services:
- POSTGRES_USER=apluser
- POSTGRES_PASSWORD=apluserpass
- POSTGRES_DB=apldb
- ganache:
- image: "trufflesuite/ganache:latest"
+ hardhat-network:
+ build:
+ context: ./
+ dockerfile: tests/Dockerfile_hardhat
ports:
- "8545:8545"
- command:
- - -k
- - 'berlin'
- - -g
- - '0'
- - --chain.chainId
- - '2017'
ibet-prime-postgres:
build:
context: ./
- dockerfile: ./tests/Dockerfile
+ dockerfile: ./tests/Dockerfile_unittest
environment:
- TEST_DATABASE_URL=postgresql+psycopg://apluser:apluserpass@postgres/apldb
- WEB3_HTTP_PROVIDER=http://quorum:8545
- RESPONSE_VALIDATION_MODE=1
links:
- postgres:postgres
- - ganache:quorum
+ - hardhat-network:quorum
depends_on:
- postgres
- - ganache
+ - hardhat-network
diff --git a/docs/generate_openapi_doc.py b/docs/generate_openapi_doc.py
new file mode 100644
index 00000000..784a42f7
--- /dev/null
+++ b/docs/generate_openapi_doc.py
@@ -0,0 +1,64 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+import os
+import sys
+
+import typer
+from ruamel.yaml import YAML
+
+path = os.path.join(os.path.dirname(__file__), "../")
+sys.path.append(path)
+
+from app.main import app
+
+
+def str_represent(dumper, data):
+ if len(data.splitlines()) > 1:
+ return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="|")
+ return dumper.represent_scalar("tag:yaml.org,2002:str", data)
+
+
+def none_represent(dumper, data):
+ return dumper.represent_scalar("tag:yaml.org,2002:null", "null")
+
+
+def main():
+ openapi_json = app.openapi()
+ yaml = YAML()
+ yaml.indent(mapping=2, sequence=4, offset=2)
+ yaml.representer.add_representer(str, str_represent)
+ yaml.representer.add_representer(type(None), none_represent)
+
+ with open(
+ os.path.abspath(
+ os.path.join(
+ os.path.dirname(__file__),
+ os.path.pardir,
+ "docs/ibet_prime.yaml",
+ ),
+ ),
+ "w",
+ encoding="utf-8",
+ ) as f:
+ yaml.dump(openapi_json, f)
+
+
+if __name__ == "__main__":
+ typer.run(main)
diff --git a/docs/ibet_prime.yaml b/docs/ibet_prime.yaml
new file mode 100644
index 00000000..ced5636b
--- /dev/null
+++ b/docs/ibet_prime.yaml
@@ -0,0 +1,13975 @@
+openapi: 3.1.0
+info:
+ title: ibet Prime
+ description: Security token management system for ibet network
+ version: '24.6'
+paths:
+ /:
+ get:
+ tags:
+ - root
+ summary: Root
+ operationId: root__get
+ responses:
+ '200':
+ description: Successful Response
+ /e2ee:
+ get:
+ tags:
+ - common
+ summary: E2E Encryption Key
+ description: Get E2EE public key
+ operationId: e2e_encryption_key_e2ee_get
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/E2EEResponse'
+ /healthcheck:
+ get:
+ tags:
+ - common
+ summary: Check Health
+ operationId: check_health_healthcheck_get
+ responses:
+ '200':
+ description: Successful Response
+ '503':
+ description: Service Unavailable Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServiceUnavailableErrorResponse'
+ /block_number:
+ get:
+ tags:
+ - common
+ summary: Get Block Number
+ description: Get the latest block number
+ operationId: get_block_number_block_number_get
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BlockNumberResponse'
+ '503':
+ description: Service Unavailable Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServiceUnavailableErrorResponse'
+ /accounts:
+ get:
+ tags:
+ - account
+ summary: List All Accounts
+ description: List all accounts
+ operationId: list_all_accounts_accounts_get
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ items:
+ $ref: '#/components/schemas/AccountResponse'
+ type: array
+ title: Response List All Accounts Accounts Get
+ post:
+ tags:
+ - account
+ summary: Create Key
+ description: Create Keys
+ operationId: create_key_accounts_post
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AccountCreateKeyRequest'
+ required: true
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AccountResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /accounts/{issuer_address}:
+ get:
+ tags:
+ - account
+ summary: Retrieve Account
+ description: Retrieve an account
+ operationId: retrieve_account_accounts__issuer_address__get
+ parameters:
+ - name: issuer_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Issuer Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AccountResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ delete:
+ tags:
+ - account
+ summary: Delete Account
+ description: Logically delete an account
+ operationId: delete_account_accounts__issuer_address__delete
+ parameters:
+ - name: issuer_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Issuer Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AccountResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /accounts/{issuer_address}/rsakey:
+ post:
+ tags:
+ - account
+ summary: Generate Rsa Key
+ description: Generate RSA key
+ operationId: generate_rsa_key_accounts__issuer_address__rsakey_post
+ parameters:
+ - name: issuer_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Issuer Address
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AccountGenerateRsaKeyRequest'
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AccountResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /accounts/{issuer_address}/eoa_password:
+ post:
+ tags:
+ - account
+ summary: Change Eoa Password
+ description: Change EOA Password
+ operationId: change_eoa_password_accounts__issuer_address__eoa_password_post
+ parameters:
+ - name: issuer_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Issuer Address
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AccountChangeEOAPasswordRequest'
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /accounts/{issuer_address}/rsa_passphrase:
+ post:
+ tags:
+ - account
+ summary: Change Rsa Passphrase
+ description: Change RSA Passphrase
+ operationId: change_rsa_passphrase_accounts__issuer_address__rsa_passphrase_post
+ parameters:
+ - name: issuer_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Issuer Address
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AccountChangeRSAPassphraseRequest'
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /accounts/{issuer_address}/auth_token:
+ post:
+ tags:
+ - account
+ summary: Create Auth Token
+ description: Create Auth Token
+ operationId: create_auth_token_accounts__issuer_address__auth_token_post
+ parameters:
+ - name: issuer_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Issuer Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AccountAuthTokenRequest'
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AccountAuthTokenResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthTokenAlreadyExistsErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ title: Response 400 Create Auth Token Accounts Issuer Address Auth
+ Token Post
+ delete:
+ tags:
+ - account
+ summary: Delete Auth Token
+ description: Delete auth token
+ operationId: delete_auth_token_accounts__issuer_address__auth_token_delete
+ parameters:
+ - name: issuer_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Issuer Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AuthorizationErrorResponse'
+ /bond/tokens:
+ post:
+ tags:
+ - bond
+ summary: Issue Token
+ description: Issue ibetStraightBond token
+ operationId: issue_token_bond_tokens_post
+ parameters:
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IbetStraightBondCreate'
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TokenAddressResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Issue Token Bond Tokens Post
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/SendTransactionErrorResponse'
+ - $ref: '#/components/schemas/ContractRevertErrorResponse'
+ title: Response 400 Issue Token Bond Tokens Post
+ get:
+ tags:
+ - bond
+ summary: List All Tokens
+ description: List all issued tokens
+ operationId: list_all_tokens_bond_tokens_get
+ parameters:
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/IbetStraightBondResponse'
+ title: Response List All Tokens Bond Tokens Get
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ /bond/tokens/{token_address}:
+ get:
+ tags:
+ - bond
+ summary: Retrieve Token
+ description: Retrieve token
+ operationId: retrieve_token_bond_tokens__token_address__get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IbetStraightBondResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ post:
+ tags:
+ - bond
+ summary: Update Token
+ description: Update a token
+ operationId: update_token_bond_tokens__token_address__post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IbetStraightBondUpdate'
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Update Token Bond Tokens Token Address Post
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/OperationNotSupportedVersionErrorResponse'
+ - $ref: '#/components/schemas/SendTransactionErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ - $ref: '#/components/schemas/ContractRevertErrorResponse'
+ title: Response 400 Update Token Bond Tokens Token Address Post
+ /bond/tokens/{token_address}/history:
+ get:
+ tags:
+ - bond
+ summary: List Bond Operation Log History
+ description: List of token operation log history
+ operationId: list_bond_operation_log_history_bond_tokens__token_address__history_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: modified_contents
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: Modified contents query
+ title: Modified Contents
+ description: Modified contents query
+ - name: operation_category
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/TokenUpdateOperationCategory'
+ - type: 'null'
+ description: Trigger of change
+ title: Operation Category
+ description: Trigger of change
+ - name: created_from
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: created datetime (From)
+ title: Created From
+ description: created datetime (From)
+ - name: created_to
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: created datetime (To)
+ title: Created To
+ description: created datetime (To)
+ - name: sort_item
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/ListTokenHistorySortItem'
+ description: Sort item
+ default: created
+ title: Sort Item
+ description: Sort item
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 'Sort order(0: ASC, 1: DESC)'
+ default: 1
+ title: Sort Order
+ description: 'Sort order(0: ASC, 1: DESC)'
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Start position
+ title: Offset
+ description: Start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Number of set
+ title: Limit
+ description: Number of set
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListTokenOperationLogHistoryResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /bond/tokens/{token_address}/additional_issue:
+ get:
+ tags:
+ - bond
+ summary: List Additional Issuance History
+ description: List additional issuance history
+ operationId:
+ list_additional_issuance_history_bond_tokens__token_address__additional_issue_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: sort_item
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/IssueRedeemSortItem'
+ default: block_timestamp
+ title: Sort Item
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 0:asc, 1:desc
+ default: 1
+ title: Sort Order
+ description: 0:asc, 1:desc
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Start position
+ title: Offset
+ description: Start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Number of set
+ title: Limit
+ description: Number of set
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IssueRedeemHistoryResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ post:
+ tags:
+ - bond
+ summary: Additional Issue
+ description: Additional issue
+ operationId: additional_issue_bond_tokens__token_address__additional_issue_post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IbetStraightBondAdditionalIssue'
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Additional Issue Bond Tokens Token Address Additional
+ Issue Post
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/SendTransactionErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ - $ref: '#/components/schemas/ContractRevertErrorResponse'
+ title: Response 400 Additional Issue Bond Tokens Token Address Additional
+ Issue Post
+ /bond/tokens/{token_address}/additional_issue/batch:
+ get:
+ tags:
+ - bond
+ summary: List All Additional Issue Upload
+ operationId:
+ list_all_additional_issue_upload_bond_tokens__token_address__additional_issue_batch_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: processed
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Processed
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 0:asc, 1:desc
+ default: 1
+ title: Sort Order
+ description: 0:asc, 1:desc
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Start position
+ title: Offset
+ description: Start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Number of set
+ title: Limit
+ description: Number of set
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListBatchIssueRedeemUploadResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ post:
+ tags:
+ - bond
+ summary: Additional Issue In Batch
+ description: Additional issue (Batch)
+ operationId:
+ additional_issue_in_batch_bond_tokens__token_address__additional_issue_batch_post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/IbetStraightBondAdditionalIssue'
+ title: Data
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BatchIssueRedeemUploadIdResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Additional Issue In Batch Bond Tokens Token Address Additional
+ Issue Batch Post
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /bond/tokens/{token_address}/additional_issue/batch/{batch_id}:
+ get:
+ tags:
+ - bond
+ summary: Retrieve Batch Additional Issue
+ description: Get Batch status for additional issue
+ operationId:
+ retrieve_batch_additional_issue_bond_tokens__token_address__additional_issue_batch__batch_id__get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: batch_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Batch Id
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetBatchIssueRedeemResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /bond/tokens/{token_address}/redeem:
+ get:
+ tags:
+ - bond
+ summary: List Redeem History
+ description: List redemption history
+ operationId: list_redeem_history_bond_tokens__token_address__redeem_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: sort_item
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/IssueRedeemSortItem'
+ default: block_timestamp
+ title: Sort Item
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 0:asc, 1:desc
+ default: 1
+ title: Sort Order
+ description: 0:asc, 1:desc
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Start position
+ title: Offset
+ description: Start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Number of set
+ title: Limit
+ description: Number of set
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IssueRedeemHistoryResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ post:
+ tags:
+ - bond
+ summary: Redeem Token
+ description: Redeem a token
+ operationId: redeem_token_bond_tokens__token_address__redeem_post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IbetStraightBondRedeem'
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Redeem Token Bond Tokens Token Address Redeem
+ Post
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/SendTransactionErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ - $ref: '#/components/schemas/ContractRevertErrorResponse'
+ title: Response 400 Redeem Token Bond Tokens Token Address Redeem
+ Post
+ /bond/tokens/{token_address}/redeem/batch:
+ get:
+ tags:
+ - bond
+ summary: List All Redeem Upload
+ operationId: list_all_redeem_upload_bond_tokens__token_address__redeem_batch_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: processed
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Processed
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 0:asc, 1:desc
+ default: 1
+ title: Sort Order
+ description: 0:asc, 1:desc
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Start position
+ title: Offset
+ description: Start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Number of set
+ title: Limit
+ description: Number of set
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListBatchIssueRedeemUploadResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ post:
+ tags:
+ - bond
+ summary: Redeem Token In Batch
+ description: Redeem a token (Batch)
+ operationId: redeem_token_in_batch_bond_tokens__token_address__redeem_batch_post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/IbetStraightBondRedeem'
+ title: Data
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BatchIssueRedeemUploadIdResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Redeem Token In Batch Bond Tokens Token Address Redeem
+ Batch Post
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /bond/tokens/{token_address}/redeem/batch/{batch_id}:
+ get:
+ tags:
+ - bond
+ summary: Retrieve Batch Redeem
+ description: Get Batch status for additional issue
+ operationId: retrieve_batch_redeem_bond_tokens__token_address__redeem_batch__batch_id__get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: batch_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Batch Id
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetBatchIssueRedeemResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /bond/tokens/{token_address}/scheduled_events:
+ get:
+ tags:
+ - bond
+ summary: List All Scheduled Events
+ description: List all scheduled update events
+ operationId: list_all_scheduled_events_bond_tokens__token_address__scheduled_events_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/ScheduledEventResponse'
+ title: Response List All Scheduled Events Bond Tokens Token Address Scheduled
+ Events Get
+ post:
+ tags:
+ - bond
+ summary: Schedule New Update Event
+ description: Register a new update event
+ operationId: schedule_new_update_event_bond_tokens__token_address__scheduled_events_post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IbetStraightBondScheduledUpdate'
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ScheduledEventIdResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Schedule New Update Event Bond Tokens Token Address Scheduled
+ Events Post
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/OperationNotSupportedVersionErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ title: Response 400 Schedule New Update Event Bond Tokens Token Address Scheduled
+ Events Post
+ /bond/tokens/{token_address}/scheduled_events/{scheduled_event_id}:
+ get:
+ tags:
+ - bond
+ summary: Retrieve Token Event
+ description: Retrieve a scheduled token event
+ operationId:
+ retrieve_token_event_bond_tokens__token_address__scheduled_events__scheduled_event_id__get
+ parameters:
+ - name: scheduled_event_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Scheduled Event Id
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ScheduledEventResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ delete:
+ tags:
+ - bond
+ summary: Delete Scheduled Event
+ description: Delete a scheduled event
+ operationId:
+ delete_scheduled_event_bond_tokens__token_address__scheduled_events__scheduled_event_id__delete
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: scheduled_event_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Scheduled Event Id
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ScheduledEventResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Delete Scheduled Event Bond Tokens Token Address Scheduled
+ Events Scheduled Event Id Delete
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /bond/tokens/{token_address}/holders:
+ get:
+ tags:
+ - bond
+ summary: List All Holders
+ description: List all bond token holders
+ operationId: list_all_holders_bond_tokens__token_address__holders_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: include_former_holder
+ in: query
+ required: false
+ schema:
+ type: boolean
+ default: false
+ title: Include Former Holder
+ - name: balance
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ description: number of balance
+ title: Balance
+ description: number of balance
+ - name: balance_operator
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/ValueOperator'
+ - type: 'null'
+ description: search condition of balance(0:equal, 1:greater than or equal,
+ 2:less than or equal)
+ default: 0
+ title: Balance Operator
+ description: search condition of balance(0:equal, 1:greater than or equal,
+ 2:less than or equal)
+ - name: pending_transfer
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ description: number of pending transfer amount
+ title: Pending Transfer
+ description: number of pending transfer amount
+ - name: pending_transfer_operator
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/ValueOperator'
+ - type: 'null'
+ description: search condition of pending transfer(0:equal, 1:greater than
+ or equal, 2:less than or equal)
+ default: 0
+ title: Pending Transfer Operator
+ description: search condition of pending transfer(0:equal, 1:greater than
+ or equal, 2:less than or equal)
+ - name: locked
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ description: number of locked amount
+ title: Locked
+ description: number of locked amount
+ - name: locked_operator
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/ValueOperator'
+ - type: 'null'
+ description: search condition of locked amount(0:equal, 1:greater than
+ or equal, 2:less than or equal)
+ default: 0
+ title: Locked Operator
+ description: search condition of locked amount(0:equal, 1:greater than or
+ equal, 2:less than or equal)
+ - name: balance_and_pending_transfer
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ description: number of balance plus pending transfer amount
+ title: Balance And Pending Transfer
+ description: number of balance plus pending transfer amount
+ - name: balance_and_pending_transfer_operator
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/ValueOperator'
+ - type: 'null'
+ description: search condition of balance plus pending transfer(0:equal,
+ 1:greater than or equal, 2:less than or equal)
+ default: 0
+ title: Balance And Pending Transfer Operator
+ description: search condition of balance plus pending transfer(0:equal,
+ 1:greater than or equal, 2:less than or equal)
+ - name: account_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: account address(partial match)
+ title: Account Address
+ description: account address(partial match)
+ - name: holder_name
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: holder name(partial match)
+ title: Holder Name
+ description: holder name(partial match)
+ - name: key_manager
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: key manager(partial match)
+ title: Key Manager
+ description: key manager(partial match)
+ - name: sort_item
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/ListAllHoldersSortItem'
+ description: Sort Item
+ default: created
+ title: Sort Item
+ description: Sort Item
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 0:asc, 1:desc
+ default: 0
+ title: Sort Order
+ description: 0:asc, 1:desc
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Start position
+ title: Offset
+ description: Start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Number of set
+ title: Limit
+ description: Number of set
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HoldersResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /bond/tokens/{token_address}/holders/count:
+ get:
+ tags:
+ - bond
+ summary: Count Number Of Holders
+ description: Count the number of holders
+ operationId: count_number_of_holders_bond_tokens__token_address__holders_count_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HolderCountResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /bond/tokens/{token_address}/holders/{account_address}:
+ get:
+ tags:
+ - bond
+ summary: Retrieve Holder
+ description: Retrieve bond token holder
+ operationId: retrieve_holder_bond_tokens__token_address__holders__account_address__get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: account_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Account Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HolderResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /bond/tokens/{token_address}/personal_info:
+ post:
+ tags:
+ - bond
+ summary: Register Holder Personal Info
+ description: Register the holder's personal information
+ operationId: register_holder_personal_info_bond_tokens__token_address__personal_info_post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/RegisterPersonalInfoRequest'
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Register Holder Personal Info Bond Tokens Token
+ Address Personal Info Post
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/SendTransactionErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ - $ref: '#/components/schemas/ContractRevertErrorResponse'
+ title: Response 400 Register Holder Personal Info Bond Tokens Token
+ Address Personal Info Post
+ /bond/tokens/{token_address}/personal_info/batch:
+ get:
+ tags:
+ - bond
+ summary: List All Personal Info Batch Registration Uploads
+ description: List all personal information batch registration uploads
+ operationId:
+ list_all_personal_info_batch_registration_uploads_bond_tokens__token_address__personal_info_batch_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: status
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Status
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 0:asc, 1:desc
+ default: 1
+ title: Sort Order
+ description: 0:asc, 1:desc
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Start position
+ title: Offset
+ description: Start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Number of set
+ title: Limit
+ description: Number of set
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListBatchRegisterPersonalInfoUploadResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ post:
+ tags:
+ - bond
+ summary: Batch Register Personal Info
+ description: Create Batch for register personal information
+ operationId:
+ batch_register_personal_info_bond_tokens__token_address__personal_info_batch_post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/RegisterPersonalInfoRequest'
+ title: Personal Info List
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BatchRegisterPersonalInfoUploadResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Batch Register Personal Info Bond Tokens Token
+ Address Personal Info Batch Post
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /bond/tokens/{token_address}/personal_info/batch/{batch_id}:
+ get:
+ tags:
+ - bond
+ summary: Retrieve Batch Register Personal Info
+ description: Get Batch status for register personal information
+ operationId:
+ retrieve_batch_register_personal_info_bond_tokens__token_address__personal_info_batch__batch_id__get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: batch_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Batch Id
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetBatchRegisterPersonalInfoResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error401Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /bond/tokens/{token_address}/lock_events:
+ get:
+ tags:
+ - bond
+ summary: List all lock/unlock events related to given bond token
+ operationId: list_all_lock_events_by_bond_bond_tokens__token_address__lock_events_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Start position
+ title: Offset
+ description: Start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Number of set
+ title: Limit
+ description: Number of set
+ - name: account_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: Account address
+ title: Account Address
+ description: Account address
+ - name: msg_sender
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: Msg sender
+ title: Msg Sender
+ description: Msg sender
+ - name: lock_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: Lock address
+ title: Lock Address
+ description: Lock address
+ - name: recipient_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: Recipient address
+ title: Recipient Address
+ description: Recipient address
+ - name: category
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/LockEventCategory'
+ - type: 'null'
+ description: Event category
+ title: Category
+ description: Event category
+ - name: sort_item
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/ListAllTokenLockEventsSortItem'
+ description: Sort item
+ default: block_timestamp
+ title: Sort Item
+ description: Sort item
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 'Sort order(0: ASC, 1: DESC)'
+ default: 1
+ title: Sort Order
+ description: 'Sort order(0: ASC, 1: DESC)'
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListAllTokenLockEventsResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ /bond/transfers:
+ post:
+ tags:
+ - bond
+ summary: Transfer Ownership
+ description: Transfer token ownership
+ operationId: transfer_ownership_bond_transfers_post
+ parameters:
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IbetStraightBondTransfer'
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Transfer Ownership Bond Transfers Post
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/SendTransactionErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ - $ref: '#/components/schemas/ContractRevertErrorResponse'
+ title: Response 400 Transfer Ownership Bond Transfers Post
+ /bond/transfers/{token_address}:
+ get:
+ tags:
+ - bond
+ summary: List Transfer History
+ description: List token transfer history
+ operationId: list_transfer_history_bond_transfers__token_address__get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: block_timestamp_from
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ format: date-time
+ - type: 'null'
+ description: block timestamp (From)
+ title: Block Timestamp From
+ description: block timestamp (From)
+ - name: block_timestamp_to
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ format: date-time
+ - type: 'null'
+ descriptio0n: block timestamp (To)
+ title: Block Timestamp To
+ - name: from_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: transfer source address
+ title: From Address
+ description: transfer source address
+ - name: to_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: transfer destination address
+ title: To Address
+ description: transfer destination address
+ - name: from_address_name
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: name of transfer source address
+ title: From Address Name
+ description: name of transfer source address
+ - name: to_address_name
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: name of transfer destination address
+ title: To Address Name
+ description: name of transfer destination address
+ - name: amount
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ description: transfer amount
+ title: Amount
+ description: transfer amount
+ - name: amount_operator
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/ValueOperator'
+ - type: 'null'
+ description: 'value filter condition(0: equal, 1: greater than, 2: less
+ than)'
+ default: 0
+ title: Amount Operator
+ description: 'value filter condition(0: equal, 1: greater than, 2: less
+ than)'
+ - name: source_event
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/TransferSourceEventType'
+ - type: 'null'
+ description: source event of transfer
+ title: Source Event
+ description: source event of transfer
+ - name: data
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: source event data
+ title: Data
+ description: source event data
+ - name: sort_item
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/ListTransferHistorySortItem'
+ description: sort item
+ default: block_timestamp
+ title: Sort Item
+ description: sort item
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 0:asc, 1:desc
+ default: 1
+ title: Sort Order
+ description: 0:asc, 1:desc
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: start position
+ title: Offset
+ description: start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: number of set
+ title: Limit
+ description: number of set
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TransferHistoryResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /bond/transfer_approvals:
+ get:
+ tags:
+ - bond
+ summary: List Transfer Approval History
+ description: List transfer approval history
+ operationId: list_transfer_approval_history_bond_transfer_approvals_get
+ parameters:
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Offset
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Limit
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TransferApprovalsResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ /bond/transfer_approvals/{token_address}:
+ get:
+ tags:
+ - bond
+ summary: List Token Transfer Approval History
+ description: List token transfer approval history
+ operationId: list_token_transfer_approval_history_bond_transfer_approvals__token_address__get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: from_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: From Address
+ - name: to_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: To Address
+ - name: status
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: array
+ items:
+ $ref: '#/components/schemas/TransferApprovalStatus'
+ - type: 'null'
+ description: 0:unapproved, 1:escrow_finished, 2:transferred, 3:canceled
+ title: Status
+ description: 0:unapproved, 1:escrow_finished, 2:transferred, 3:canceled
+ - name: sort_item
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/ListTransferApprovalHistorySortItem'
+ - type: 'null'
+ default: id
+ title: Sort Item
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 0:asc, 1:desc
+ default: 1
+ title: Sort Order
+ description: 0:asc, 1:desc
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: start position
+ title: Offset
+ description: start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: number of set
+ title: Limit
+ description: number of set
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TransferApprovalHistoryResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /bond/transfer_approvals/{token_address}/{id}:
+ post:
+ tags:
+ - bond
+ summary: Update Transfer Approval
+ description: Update on the status of a bond transfer approval
+ operationId: update_transfer_approval_bond_transfer_approvals__token_address___id__post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: integer
+ title: Id
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdateTransferApprovalRequest'
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Update Transfer Approval Bond Transfer Approvals Token
+ Address Id Post
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/OperationNotAllowedStateErrorResponse'
+ - $ref: '#/components/schemas/SendTransactionErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ - $ref: '#/components/schemas/ContractRevertErrorResponse'
+ title: Response 400 Update Transfer Approval Bond Transfer Approvals Token
+ Address Id Post
+ get:
+ tags:
+ - bond
+ summary: Retrieve Transfer Approval History
+ description: Retrieve bond token transfer approval history
+ operationId:
+ retrieve_transfer_approval_history_bond_transfer_approvals__token_address___id__get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: integer
+ title: Id
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TransferApprovalTokenDetailResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /bond/bulk_transfer:
+ post:
+ tags:
+ - bond
+ summary: Bulk Transfer Ownership
+ description: |-
+ Bulk transfer token ownership
+
+ By using "transaction compression mode", it is possible to consolidate multiple transfers into one transaction.
+ This speeds up the time it takes for all transfers to be completed.
+ On the other hand, when using transaction compression, the input data must meet the following conditions.
+ - All `token_address` must be the same.
+ - All `from_address` must be the same.
+ - `from_address` and `issuer_address` must be the same.
+ operationId: bulk_transfer_ownership_bond_bulk_transfer_post
+ parameters:
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IbetStraightBondBulkTransferRequest'
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BulkTransferUploadIdResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Bulk Transfer Ownership Bond Bulk Transfer Post
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ get:
+ tags:
+ - bond
+ summary: List Bulk Transfer Upload
+ description: List bulk transfer uploads
+ operationId: list_bulk_transfer_upload_bond_bulk_transfer_get
+ parameters:
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/BulkTransferUploadResponse'
+ title: Response List Bulk Transfer Upload Bond Bulk Transfer Get
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ /bond/bulk_transfer/{upload_id}:
+ get:
+ tags:
+ - bond
+ summary: Retrieve Bulk Transfer
+ description: Retrieve a bulk transfer upload
+ operationId: retrieve_bulk_transfer_bond_bulk_transfer__upload_id__get
+ parameters:
+ - name: upload_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Upload Id
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/BulkTransferResponse'
+ title: Response Retrieve Bulk Transfer Bond Bulk Transfer Upload
+ Id Get
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /e2e_messaging/accounts:
+ get:
+ tags:
+ - messaging
+ summary: List All Accounts
+ description: List all e2e messaging accounts
+ operationId: list_all_accounts_e2e_messaging_accounts_get
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ items:
+ $ref: '#/components/schemas/E2EMessagingAccountResponse'
+ type: array
+ title: Response List All Accounts E2E Messaging Accounts Get
+ post:
+ tags:
+ - messaging
+ summary: Create Account
+ description: Create Account
+ operationId: create_account_e2e_messaging_accounts_post
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/E2EMessagingAccountCreateRequest'
+ required: true
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/E2EMessagingAccountResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/SendTransactionErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ - $ref: '#/components/schemas/ContractRevertErrorResponse'
+ title: Response 400 Create Account E2E Messaging Accounts Post
+ /e2e_messaging/accounts/{account_address}:
+ get:
+ tags:
+ - messaging
+ summary: Retrieve Account
+ description: Retrieve an e2e messaging account
+ operationId: retrieve_account_e2e_messaging_accounts__account_address__get
+ parameters:
+ - name: account_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Account Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/E2EMessagingAccountResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ delete:
+ tags:
+ - messaging
+ summary: Delete Account
+ description: Logically delete an e2e messaging account
+ operationId: delete_account_e2e_messaging_accounts__account_address__delete
+ parameters:
+ - name: account_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Account Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/E2EMessagingAccountResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /e2e_messaging/accounts/{account_address}/rsa_key:
+ post:
+ tags:
+ - messaging
+ summary: Update Account Rsa Key
+ description: Update an e2e messaging account rsa key
+ operationId: update_account_rsa_key_e2e_messaging_accounts__account_address__rsa_key_post
+ parameters:
+ - name: account_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Account Address
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/E2EMessagingAccountUpdateRsaKeyRequest'
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/E2EMessagingAccountResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /e2e_messaging/accounts/{account_address}/eoa_password:
+ post:
+ tags:
+ - messaging
+ summary: Change Eoa Password
+ description: Change Account's EOA Password
+ operationId: change_eoa_password_e2e_messaging_accounts__account_address__eoa_password_post
+ parameters:
+ - name: account_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Account Address
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/E2EMessagingAccountChangeEOAPasswordRequest'
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /e2e_messaging/accounts/{account_address}/rsa_passphrase:
+ post:
+ tags:
+ - messaging
+ summary: Change Rsa Passphrase
+ description: Change Account's RSA Passphrase
+ operationId:
+ change_rsa_passphrase_e2e_messaging_accounts__account_address__rsa_passphrase_post
+ parameters:
+ - name: account_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Account Address
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/E2EMessagingAccountChangeRSAPassphraseRequest'
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /e2e_messaging/messages:
+ get:
+ tags:
+ - messaging
+ summary: List All E2E Messages
+ description: List all e2e message
+ operationId: list_all_e2e_messages_e2e_messaging_messages_get
+ parameters:
+ - name: from_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: From Address
+ - name: to_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: To Address
+ - name: type
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Type
+ - name: message
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: partial match
+ title: Message
+ description: partial match
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Offset
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Limit
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListAllE2EMessagingResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ /e2e_messaging/messages/{id}:
+ get:
+ tags:
+ - messaging
+ summary: Retrieve E2E Messaging
+ description: Retrieve an e2e message
+ operationId: retrieve_e2e_messaging_e2e_messaging_messages__id__get
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: integer
+ title: Id
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/E2EMessagingResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /files:
+ get:
+ tags:
+ - utility
+ summary: List All Upload Files
+ description: List all files
+ operationId: list_all_upload_files_files_get
+ parameters:
+ - name: relation
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Relation
+ - name: file_name
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: partial match
+ title: File Name
+ description: partial match
+ - name: label
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: partial match
+ title: Label
+ description: partial match
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Offset
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Limit
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListAllFilesResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ post:
+ tags:
+ - utility
+ summary: Upload File
+ description: Upload file
+ operationId: upload_file_files_post
+ parameters:
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UploadFileRequest'
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/FileResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ /files/{file_id}:
+ get:
+ tags:
+ - utility
+ summary: Download File
+ description: Download file
+ operationId: download_file_files__file_id__get
+ parameters:
+ - name: file_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: File Id
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DownloadFileResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ delete:
+ tags:
+ - utility
+ summary: Delete File
+ description: Delete file
+ operationId: delete_file_files__file_id__delete
+ parameters:
+ - name: file_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: File Id
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /ledger/{token_address}/history:
+ get:
+ tags:
+ - token_common
+ summary: List All Ledger History
+ description: List all Ledger
+ operationId: list_all_ledger_history_ledger__token_address__history_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: offset
+ in: query
+ required: false
+ schema:
+ type: integer
+ title: Offset
+ - name: limit
+ in: query
+ required: false
+ schema:
+ type: integer
+ title: Limit
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListAllLedgerHistoryResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /ledger/{token_address}/history/{ledger_id}:
+ get:
+ tags:
+ - token_common
+ summary: Retrieve Ledger History
+ description: Retrieve Ledger
+ operationId: retrieve_ledger_history_ledger__token_address__history__ledger_id__get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: ledger_id
+ in: path
+ required: true
+ schema:
+ type: integer
+ title: Ledger Id
+ - name: latest_flg
+ in: query
+ required: true
+ schema:
+ type: integer
+ maximum: 1
+ minimum: 0
+ title: Latest Flg
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/RetrieveLedgerHistoryResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/Integer64bitLimitExceededErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ title: Response 400 Retrieve Ledger History Ledger Token Address History Ledger
+ Id Get
+ /ledger/{token_address}/template:
+ get:
+ tags:
+ - token_common
+ summary: Retrieve Ledger Template
+ description: Retrieve Ledger Template
+ operationId: retrieve_ledger_template_ledger__token_address__template_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/LedgerTemplateResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ post:
+ tags:
+ - token_common
+ summary: Create Update Ledger Template
+ description: Create or Update Ledger Template
+ operationId: create_update_ledger_template_ledger__token_address__template_post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateUpdateLedgerTemplateRequest'
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ delete:
+ tags:
+ - token_common
+ summary: Delete Ledger Template
+ description: Delete Ledger Template
+ operationId: delete_ledger_template_ledger__token_address__template_delete
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /ledger/{token_address}/details_data:
+ get:
+ tags:
+ - token_common
+ summary: List All Ledger Details Data
+ description: List all Ledger Details Data
+ operationId: list_all_ledger_details_data_ledger__token_address__details_data_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: offset
+ in: query
+ required: false
+ schema:
+ type: integer
+ title: Offset
+ - name: limit
+ in: query
+ required: false
+ schema:
+ type: integer
+ title: Limit
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListAllLedgerDetailsDataResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ post:
+ tags:
+ - token_common
+ summary: Create Ledger Details Data
+ description: Create Ledger Details Data
+ operationId: create_ledger_details_data_ledger__token_address__details_data_post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/CreateUpdateLedgerDetailsDataRequest'
+ title: Data List
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/LedgerDetailsDataResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /ledger/{token_address}/details_data/{data_id}:
+ get:
+ tags:
+ - token_common
+ summary: Retrieve Ledger Details Data
+ description: Retrieve Ledger Details Data
+ operationId: retrieve_ledger_details_data_ledger__token_address__details_data__data_id__get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: data_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Data Id
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/RetrieveLedgerDetailsDataResponse'
+ title: Response Retrieve Ledger Details Data Ledger Token Address Details
+ Data Data Id Get
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ post:
+ tags:
+ - token_common
+ summary: Update Ledger Details Data
+ description: Update Ledger Details Data
+ operationId: update_ledger_details_data_ledger__token_address__details_data__data_id__post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: data_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Data Id
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/CreateUpdateLedgerDetailsDataRequest'
+ title: Data List
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ delete:
+ tags:
+ - token_common
+ summary: Delete Ledger Details Data
+ description: Delete Ledger Details Data
+ operationId: delete_ledger_details_data_ledger__token_address__details_data__data_id__delete
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: data_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Data Id
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /notifications:
+ get:
+ tags:
+ - notification
+ summary: List All Notifications
+ description: List all notifications
+ operationId: list_all_notifications_notifications_get
+ parameters:
+ - name: notice_type
+ in: query
+ required: false
+ schema:
+ type: string
+ title: Notice Type
+ - name: offset
+ in: query
+ required: false
+ schema:
+ type: integer
+ title: Offset
+ - name: limit
+ in: query
+ required: false
+ schema:
+ type: integer
+ title: Limit
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListAllNotificationsResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ /notifications/{notice_id}:
+ delete:
+ tags:
+ - notification
+ summary: Delete Notification
+ description: Delete notification
+ operationId: delete_notification_notifications__notice_id__delete
+ parameters:
+ - name: notice_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Notice Id
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /positions/{account_address}:
+ get:
+ tags:
+ - token_common
+ summary: List all positions in the account
+ description: List all account's position
+ operationId: list_all_position_positions__account_address__get
+ parameters:
+ - name: account_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Account Address
+ - name: include_former_position
+ in: query
+ required: false
+ schema:
+ type: boolean
+ default: false
+ title: Include Former Position
+ - name: token_type
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/TokenType'
+ - type: 'null'
+ title: Token Type
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Offset
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Limit
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListAllPositionResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ /positions/{account_address}/lock:
+ get:
+ tags:
+ - token_common
+ summary: List all locked positions in the account
+ description: List all account's locked position
+ operationId: list_all_locked_position_positions__account_address__lock_get
+ parameters:
+ - name: account_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Account Address
+ - name: token_type
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/TokenType'
+ - type: 'null'
+ title: Token Type
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Offset
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Limit
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListAllLockedPositionResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ /positions/{account_address}/lock/events:
+ get:
+ tags:
+ - token_common
+ summary: List all lock/unlock events in the account
+ description: List all lock/unlock events in the account
+ operationId: list_all_lock_events_positions__account_address__lock_events_get
+ parameters:
+ - name: account_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Account Address
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Start position
+ title: Offset
+ description: Start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Number of set
+ title: Limit
+ description: Number of set
+ - name: token_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: Token address
+ title: Token Address
+ description: Token address
+ - name: token_type
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/TokenType'
+ - type: 'null'
+ description: Token type
+ title: Token Type
+ description: Token type
+ - name: msg_sender
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: Msg sender
+ title: Msg Sender
+ description: Msg sender
+ - name: lock_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: Lock address
+ title: Lock Address
+ description: Lock address
+ - name: recipient_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: Recipient address
+ title: Recipient Address
+ description: Recipient address
+ - name: category
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/LockEventCategory'
+ - type: 'null'
+ description: Event category
+ title: Category
+ description: Event category
+ - name: sort_item
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/ListAllLockEventsSortItem'
+ description: Sort item
+ default: block_timestamp
+ title: Sort Item
+ description: Sort item
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 'Sort order(0: ASC, 1: DESC)'
+ default: 1
+ title: Sort Order
+ description: 'Sort order(0: ASC, 1: DESC)'
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListAllLockEventsResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ /positions/{account_address}/force_unlock:
+ post:
+ tags:
+ - token_common
+ summary: Force unlock the locked position
+ description: Force unlock the locked position
+ operationId: force_unlock_positions__account_address__force_unlock_post
+ parameters:
+ - name: account_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Account Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ForceUnlockRequest'
+ responses:
+ '200':
+ description: Successful Response
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Force Unlock Positions Account Address Force
+ Unlock Post
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/SendTransactionErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ - $ref: '#/components/schemas/ContractRevertErrorResponse'
+ title: Response 400 Force Unlock Positions Account Address Force
+ Unlock Post
+ /positions/{account_address}/{token_address}:
+ get:
+ tags:
+ - token_common
+ summary: Token position in the account
+ description: Retrieve account's position
+ operationId: retrieve_position_positions__account_address___token_address__get
+ parameters:
+ - name: account_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Account Address
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PositionResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /share/tokens:
+ post:
+ tags:
+ - share
+ summary: Issue Token
+ description: Issue ibetShare token
+ operationId: issue_token_share_tokens_post
+ parameters:
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IbetShareCreate'
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TokenAddressResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Issue Token Share Tokens Post
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/SendTransactionErrorResponse'
+ - $ref: '#/components/schemas/ContractRevertErrorResponse'
+ title: Response 400 Issue Token Share Tokens Post
+ get:
+ tags:
+ - share
+ summary: List All Tokens
+ operationId: list_all_tokens_share_tokens_get
+ parameters:
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/IbetShareResponse'
+ title: Response List All Tokens Share Tokens Get
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ /share/tokens/{token_address}:
+ get:
+ tags:
+ - share
+ summary: Retrieve Token
+ description: Retrieve token
+ operationId: retrieve_token_share_tokens__token_address__get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IbetShareResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ post:
+ tags:
+ - share
+ summary: Update Token
+ description: Update a token
+ operationId: update_token_share_tokens__token_address__post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IbetShareUpdate'
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Update Token Share Tokens Token Address Post
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/OperationNotSupportedVersionErrorResponse'
+ - $ref: '#/components/schemas/SendTransactionErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ - $ref: '#/components/schemas/ContractRevertErrorResponse'
+ title: Response 400 Update Token Share Tokens Token Address Post
+ /share/tokens/{token_address}/history:
+ get:
+ tags:
+ - share
+ summary: List Share Operation Log History
+ description: List of token operation log history
+ operationId: list_share_operation_log_history_share_tokens__token_address__history_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: modified_contents
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: Modified contents query
+ title: Modified Contents
+ description: Modified contents query
+ - name: operation_category
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/TokenUpdateOperationCategory'
+ - type: 'null'
+ description: Trigger of change
+ title: Operation Category
+ description: Trigger of change
+ - name: created_from
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: created datetime (From)
+ title: Created From
+ description: created datetime (From)
+ - name: created_to
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: created datetime (To)
+ title: Created To
+ description: created datetime (To)
+ - name: sort_item
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/ListTokenHistorySortItem'
+ description: Sort item
+ default: created
+ title: Sort Item
+ description: Sort item
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 'Sort order(0: ASC, 1: DESC)'
+ default: 1
+ title: Sort Order
+ description: 'Sort order(0: ASC, 1: DESC)'
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Start position
+ title: Offset
+ description: Start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Number of set
+ title: Limit
+ description: Number of set
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListTokenOperationLogHistoryResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /share/tokens/{token_address}/additional_issue:
+ get:
+ tags:
+ - share
+ summary: List Additional Issuance History
+ description: List additional issuance history
+ operationId:
+ list_additional_issuance_history_share_tokens__token_address__additional_issue_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: sort_item
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/IssueRedeemSortItem'
+ default: block_timestamp
+ title: Sort Item
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 0:asc, 1:desc
+ default: 1
+ title: Sort Order
+ description: 0:asc, 1:desc
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Start position
+ title: Offset
+ description: Start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Number of set
+ title: Limit
+ description: Number of set
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IssueRedeemHistoryResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ post:
+ tags:
+ - share
+ summary: Additional Issue
+ description: Additional issue
+ operationId: additional_issue_share_tokens__token_address__additional_issue_post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IbetShareAdditionalIssue'
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Additional Issue Share Tokens Token Address Additional
+ Issue Post
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/SendTransactionErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ - $ref: '#/components/schemas/ContractRevertErrorResponse'
+ title: Response 400 Additional Issue Share Tokens Token Address Additional
+ Issue Post
+ /share/tokens/{token_address}/additional_issue/batch:
+ get:
+ tags:
+ - share
+ summary: List All Additional Issue Upload
+ operationId:
+ list_all_additional_issue_upload_share_tokens__token_address__additional_issue_batch_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: processed
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Processed
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 0:asc, 1:desc
+ default: 1
+ title: Sort Order
+ description: 0:asc, 1:desc
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Start position
+ title: Offset
+ description: Start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Number of set
+ title: Limit
+ description: Number of set
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListBatchIssueRedeemUploadResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ post:
+ tags:
+ - share
+ summary: Additional Issue In Batch
+ description: Additional issue (Batch)
+ operationId:
+ additional_issue_in_batch_share_tokens__token_address__additional_issue_batch_post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/IbetShareAdditionalIssue'
+ title: Data
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BatchIssueRedeemUploadIdResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Additional Issue In Batch Share Tokens Token
+ Address Additional Issue Batch Post
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /share/tokens/{token_address}/additional_issue/batch/{batch_id}:
+ get:
+ tags:
+ - share
+ summary: Retrieve Batch Additional Issue
+ description: Get Batch status for additional issue
+ operationId:
+ retrieve_batch_additional_issue_share_tokens__token_address__additional_issue_batch__batch_id__get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: batch_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Batch Id
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetBatchIssueRedeemResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /share/tokens/{token_address}/redeem:
+ get:
+ tags:
+ - share
+ summary: List Redeem History
+ description: List redemption history
+ operationId: list_redeem_history_share_tokens__token_address__redeem_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: sort_item
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/IssueRedeemSortItem'
+ default: block_timestamp
+ title: Sort Item
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 0:asc, 1:desc
+ default: 1
+ title: Sort Order
+ description: 0:asc, 1:desc
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Start position
+ title: Offset
+ description: Start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Number of set
+ title: Limit
+ description: Number of set
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IssueRedeemHistoryResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ post:
+ tags:
+ - share
+ summary: Redeem Token
+ description: Redeem a token
+ operationId: redeem_token_share_tokens__token_address__redeem_post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IbetShareRedeem'
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Redeem Token Share Tokens Token Address Redeem
+ Post
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/SendTransactionErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ - $ref: '#/components/schemas/ContractRevertErrorResponse'
+ title: Response 400 Redeem Token Share Tokens Token Address Redeem
+ Post
+ /share/tokens/{token_address}/redeem/batch:
+ get:
+ tags:
+ - share
+ summary: List All Redeem Upload
+ operationId: list_all_redeem_upload_share_tokens__token_address__redeem_batch_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: processed
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Processed
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 0:asc, 1:desc
+ default: 1
+ title: Sort Order
+ description: 0:asc, 1:desc
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Start position
+ title: Offset
+ description: Start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Number of set
+ title: Limit
+ description: Number of set
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListBatchIssueRedeemUploadResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ post:
+ tags:
+ - share
+ summary: Redeem Token In Batch
+ description: Redeem a token (Batch)
+ operationId: redeem_token_in_batch_share_tokens__token_address__redeem_batch_post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/IbetShareRedeem'
+ title: Data
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BatchIssueRedeemUploadIdResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Redeem Token In Batch Share Tokens Token Address Redeem
+ Batch Post
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /share/tokens/{token_address}/redeem/batch/{batch_id}:
+ get:
+ tags:
+ - share
+ summary: Retrieve Batch Redeem
+ description: Get Batch status for additional issue
+ operationId: retrieve_batch_redeem_share_tokens__token_address__redeem_batch__batch_id__get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: batch_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Batch Id
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetBatchIssueRedeemResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /share/tokens/{token_address}/scheduled_events:
+ get:
+ tags:
+ - share
+ summary: List All Scheduled Events
+ description: List all scheduled update events
+ operationId: list_all_scheduled_events_share_tokens__token_address__scheduled_events_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/ScheduledEventResponse'
+ title: Response List All Scheduled Events Share Tokens Token Address Scheduled
+ Events Get
+ post:
+ tags:
+ - share
+ summary: Schedule New Update Event
+ description: Register a new update event
+ operationId: schedule_new_update_event_share_tokens__token_address__scheduled_events_post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IbetShareScheduledUpdate'
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ScheduledEventIdResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Schedule New Update Event Share Tokens Token
+ Address Scheduled Events Post
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/OperationNotSupportedVersionErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ title: Response 400 Schedule New Update Event Share Tokens Token
+ Address Scheduled Events Post
+ /share/tokens/{token_address}/scheduled_events/{scheduled_event_id}:
+ get:
+ tags:
+ - share
+ summary: Retrieve Token Event
+ description: Retrieve a scheduled token event
+ operationId:
+ retrieve_token_event_share_tokens__token_address__scheduled_events__scheduled_event_id__get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: scheduled_event_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Scheduled Event Id
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ScheduledEventResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ delete:
+ tags:
+ - share
+ summary: Delete Scheduled Event
+ description: Delete a scheduled event
+ operationId:
+ delete_scheduled_event_share_tokens__token_address__scheduled_events__scheduled_event_id__delete
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: scheduled_event_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Scheduled Event Id
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ScheduledEventResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Delete Scheduled Event Share Tokens Token Address Scheduled
+ Events Scheduled Event Id Delete
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /share/tokens/{token_address}/holders:
+ get:
+ tags:
+ - share
+ summary: List All Holders
+ description: List all share token holders
+ operationId: list_all_holders_share_tokens__token_address__holders_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: include_former_holder
+ in: query
+ required: false
+ schema:
+ type: boolean
+ default: false
+ title: Include Former Holder
+ - name: balance
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ description: number of balance
+ title: Balance
+ description: number of balance
+ - name: balance_operator
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/ValueOperator'
+ - type: 'null'
+ description: search condition of balance(0:equal, 1:greater than or equal,
+ 2:less than or equal)
+ default: 0
+ title: Balance Operator
+ description: search condition of balance(0:equal, 1:greater than or equal,
+ 2:less than or equal)
+ - name: pending_transfer
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ description: number of pending transfer amount
+ title: Pending Transfer
+ description: number of pending transfer amount
+ - name: pending_transfer_operator
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/ValueOperator'
+ - type: 'null'
+ description: search condition of pending transfer(0:equal, 1:greater than
+ or equal, 2:less than or equal)
+ default: 0
+ title: Pending Transfer Operator
+ description: search condition of pending transfer(0:equal, 1:greater than
+ or equal, 2:less than or equal)
+ - name: locked
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ description: number of locked amount
+ title: Locked
+ description: number of locked amount
+ - name: locked_operator
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/ValueOperator'
+ - type: 'null'
+ description: search condition of locked amount(0:equal, 1:greater than
+ or equal, 2:less than or equal)
+ default: 0
+ title: Locked Operator
+ description: search condition of locked amount(0:equal, 1:greater than or
+ equal, 2:less than or equal)
+ - name: balance_and_pending_transfer
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ description: number of balance plus pending transfer amount
+ title: Balance And Pending Transfer
+ description: number of balance plus pending transfer amount
+ - name: balance_and_pending_transfer_operator
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/ValueOperator'
+ - type: 'null'
+ description: search condition of balance plus pending transfer(0:equal,
+ 1:greater than or equal, 2:less than or equal)
+ default: 0
+ title: Balance And Pending Transfer Operator
+ description: search condition of balance plus pending transfer(0:equal,
+ 1:greater than or equal, 2:less than or equal)
+ - name: account_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: account address(partial match)
+ title: Account Address
+ description: account address(partial match)
+ - name: holder_name
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: holder name(partial match)
+ title: Holder Name
+ description: holder name(partial match)
+ - name: key_manager
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: key manager(partial match)
+ title: Key Manager
+ description: key manager(partial match)
+ - name: sort_item
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/ListAllHoldersSortItem'
+ description: Sort Item
+ default: created
+ title: Sort Item
+ description: Sort Item
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 0:asc, 1:desc
+ default: 0
+ title: Sort Order
+ description: 0:asc, 1:desc
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Start position
+ title: Offset
+ description: Start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Number of set
+ title: Limit
+ description: Number of set
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HoldersResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /share/tokens/{token_address}/holders/count:
+ get:
+ tags:
+ - share
+ summary: Count Number Of Holders
+ description: Count the number of holders
+ operationId: count_number_of_holders_share_tokens__token_address__holders_count_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HolderCountResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /share/tokens/{token_address}/holders/{account_address}:
+ get:
+ tags:
+ - share
+ summary: Retrieve Holder
+ description: Retrieve share token holder
+ operationId: retrieve_holder_share_tokens__token_address__holders__account_address__get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: account_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Account Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HolderResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /share/tokens/{token_address}/personal_info:
+ post:
+ tags:
+ - share
+ summary: Register Holder Personal Info
+ description: Register the holder's personal information
+ operationId: register_holder_personal_info_share_tokens__token_address__personal_info_post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/RegisterPersonalInfoRequest'
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Register Holder Personal Info Share Tokens Token
+ Address Personal Info Post
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/SendTransactionErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ - $ref: '#/components/schemas/ContractRevertErrorResponse'
+ title: Response 400 Register Holder Personal Info Share Tokens Token
+ Address Personal Info Post
+ /share/tokens/{token_address}/personal_info/batch:
+ get:
+ tags:
+ - share
+ summary: List All Personal Info Batch Registration Uploads
+ description: List all personal information batch registration uploads
+ operationId:
+ list_all_personal_info_batch_registration_uploads_share_tokens__token_address__personal_info_batch_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: status
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Status
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 0:asc, 1:desc
+ default: 1
+ title: Sort Order
+ description: 0:asc, 1:desc
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Start position
+ title: Offset
+ description: Start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Number of set
+ title: Limit
+ description: Number of set
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListBatchRegisterPersonalInfoUploadResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ post:
+ tags:
+ - share
+ summary: Batch Register Personal Info
+ description: Create Batch for register personal information
+ operationId:
+ batch_register_personal_info_share_tokens__token_address__personal_info_batch_post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/RegisterPersonalInfoRequest'
+ title: Personal Info List
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BatchRegisterPersonalInfoUploadResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Batch Register Personal Info Share Tokens Token
+ Address Personal Info Batch Post
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /share/tokens/{token_address}/personal_info/batch/{batch_id}:
+ get:
+ tags:
+ - share
+ summary: Retrieve Batch Register Personal Info
+ description: Get Batch status for register personal information
+ operationId:
+ retrieve_batch_register_personal_info_share_tokens__token_address__personal_info_batch__batch_id__get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: batch_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Batch Id
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetBatchRegisterPersonalInfoResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /share/tokens/{token_address}/lock_events:
+ get:
+ tags:
+ - share
+ summary: List all lock/unlock events related to given share token
+ operationId: list_all_lock_events_by_share_share_tokens__token_address__lock_events_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Start position
+ title: Offset
+ description: Start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Number of set
+ title: Limit
+ description: Number of set
+ - name: account_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: Account address
+ title: Account Address
+ description: Account address
+ - name: msg_sender
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: Msg sender
+ title: Msg Sender
+ description: Msg sender
+ - name: lock_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: Lock address
+ title: Lock Address
+ description: Lock address
+ - name: recipient_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: Recipient address
+ title: Recipient Address
+ description: Recipient address
+ - name: category
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/LockEventCategory'
+ - type: 'null'
+ description: Event category
+ title: Category
+ description: Event category
+ - name: sort_item
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/ListAllTokenLockEventsSortItem'
+ description: Sort item
+ default: block_timestamp
+ title: Sort Item
+ description: Sort item
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 'Sort order(0: ASC, 1: DESC)'
+ default: 1
+ title: Sort Order
+ description: 'Sort order(0: ASC, 1: DESC)'
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListAllTokenLockEventsResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ /share/transfers:
+ post:
+ tags:
+ - share
+ summary: Transfer Ownership
+ description: Transfer token ownership
+ operationId: transfer_ownership_share_transfers_post
+ parameters:
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IbetShareTransfer'
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Transfer Ownership Share Transfers Post
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/SendTransactionErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ - $ref: '#/components/schemas/ContractRevertErrorResponse'
+ title: Response 400 Transfer Ownership Share Transfers Post
+ /share/transfers/{token_address}:
+ get:
+ tags:
+ - share
+ summary: List Transfer History
+ description: List token transfer history
+ operationId: list_transfer_history_share_transfers__token_address__get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: block_timestamp_from
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ format: date-time
+ - type: 'null'
+ description: block timestamp (From)
+ title: Block Timestamp From
+ description: block timestamp (From)
+ - name: block_timestamp_to
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ format: date-time
+ - type: 'null'
+ descriptio0n: block timestamp (To)
+ title: Block Timestamp To
+ - name: from_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: transfer source address
+ title: From Address
+ description: transfer source address
+ - name: to_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: transfer destination address
+ title: To Address
+ description: transfer destination address
+ - name: from_address_name
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: name of transfer source address
+ title: From Address Name
+ description: name of transfer source address
+ - name: to_address_name
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: name of transfer destination address
+ title: To Address Name
+ description: name of transfer destination address
+ - name: amount
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ description: transfer amount
+ title: Amount
+ description: transfer amount
+ - name: amount_operator
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/ValueOperator'
+ - type: 'null'
+ description: 'value filter condition(0: equal, 1: greater than, 2: less
+ than)'
+ default: 0
+ title: Amount Operator
+ description: 'value filter condition(0: equal, 1: greater than, 2: less
+ than)'
+ - name: source_event
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/TransferSourceEventType'
+ - type: 'null'
+ description: source event of transfer
+ title: Source Event
+ description: source event of transfer
+ - name: data
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: source event data
+ title: Data
+ description: source event data
+ - name: sort_item
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/ListTransferHistorySortItem'
+ description: sort item
+ default: block_timestamp
+ title: Sort Item
+ description: sort item
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 0:asc, 1:desc
+ default: 1
+ title: Sort Order
+ description: 0:asc, 1:desc
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: start position
+ title: Offset
+ description: start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: number of set
+ title: Limit
+ description: number of set
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TransferHistoryResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /share/transfer_approvals:
+ get:
+ tags:
+ - share
+ summary: List Transfer Approval History
+ description: List transfer approval history
+ operationId: list_transfer_approval_history_share_transfer_approvals_get
+ parameters:
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Offset
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Limit
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TransferApprovalsResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ /share/transfer_approvals/{token_address}:
+ get:
+ tags:
+ - share
+ summary: List Token Transfer Approval History
+ description: List token transfer approval history
+ operationId:
+ list_token_transfer_approval_history_share_transfer_approvals__token_address__get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: from_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: From Address
+ - name: to_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: To Address
+ - name: status
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: array
+ items:
+ $ref: '#/components/schemas/TransferApprovalStatus'
+ - type: 'null'
+ description: 0:unapproved, 1:escrow_finished, 2:transferred, 3:canceled
+ title: Status
+ description: 0:unapproved, 1:escrow_finished, 2:transferred, 3:canceled
+ - name: sort_item
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/ListTransferApprovalHistorySortItem'
+ - type: 'null'
+ default: id
+ title: Sort Item
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 0:asc, 1:desc
+ default: 1
+ title: Sort Order
+ description: 0:asc, 1:desc
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: start position
+ title: Offset
+ description: start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: number of set
+ title: Limit
+ description: number of set
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TransferApprovalHistoryResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /share/transfer_approvals/{token_address}/{id}:
+ post:
+ tags:
+ - share
+ summary: Update Transfer Approval
+ description: Update on the status of a share transfer approval
+ operationId: update_transfer_approval_share_transfer_approvals__token_address___id__post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: integer
+ title: Id
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdateTransferApprovalRequest'
+ responses:
+ '200':
+ description: Successful Response
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Update Transfer Approval Share Transfer Approvals Token
+ Address Id Post
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/OperationNotAllowedStateErrorResponse'
+ - $ref: '#/components/schemas/SendTransactionErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ - $ref: '#/components/schemas/ContractRevertErrorResponse'
+ title: Response 400 Update Transfer Approval Share Transfer Approvals Token
+ Address Id Post
+ get:
+ tags:
+ - share
+ summary: Retrieve Transfer Approval History
+ description: Retrieve share token transfer approval history
+ operationId:
+ retrieve_transfer_approval_history_share_transfer_approvals__token_address___id__get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: integer
+ title: Id
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TransferApprovalTokenDetailResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /share/bulk_transfer:
+ post:
+ tags:
+ - share
+ summary: Bulk Transfer Ownership
+ description: |-
+ Bulk transfer token ownership
+
+ By using "transaction compression mode", it is possible to consolidate multiple transfers into one transaction.
+ This speeds up the time it takes for all transfers to be completed.
+ On the other hand, when using transaction compression, the input data must meet the following conditions.
+ - All `token_address` must be the same.
+ - All `from_address` must be the same.
+ - `from_address` and `issuer_address` must be the same.
+ operationId: bulk_transfer_ownership_share_bulk_transfer_post
+ parameters:
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IbetShareBulkTransferRequest'
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BulkTransferUploadIdResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '401':
+ description: Authorization Error
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/AuthorizationErrorResponse'
+ - $ref: '#/components/schemas/Error401Model'
+ title: Response 401 Bulk Transfer Ownership Share Bulk Transfer Post
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ get:
+ tags:
+ - share
+ summary: List Bulk Transfer Upload
+ description: List bulk transfer uploads
+ operationId: list_bulk_transfer_upload_share_bulk_transfer_get
+ parameters:
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/BulkTransferUploadResponse'
+ title: Response List Bulk Transfer Upload Share Bulk Transfer Get
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ /share/bulk_transfer/{upload_id}:
+ get:
+ tags:
+ - share
+ summary: Retrieve Bulk Transfer
+ description: Retrieve a bulk transfer upload
+ operationId: retrieve_bulk_transfer_share_bulk_transfer__upload_id__get
+ parameters:
+ - name: upload_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Upload Id
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/BulkTransferResponse'
+ title: Response Retrieve Bulk Transfer Share Bulk Transfer Upload
+ Id Get
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /token/holders/personal_info:
+ get:
+ tags:
+ - token_common
+ summary: List All Token Holders Personal Info
+ description: Lists the personal information of all registered holders linked
+ to the token issuer
+ operationId: ListTokenHoldersPersonalInfo
+ parameters:
+ - name: account_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: account address
+ title: Account Address
+ description: account address
+ - name: created_from
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: created datetime (From)
+ title: Created From
+ description: created datetime (From)
+ - name: created_to
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: created datetime (To)
+ title: Created To
+ description: created datetime (To)
+ - name: modified_from
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: modified datetime (From)
+ title: Modified From
+ description: modified datetime (From)
+ - name: modified_to
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: modified datetime (To)
+ title: Modified To
+ description: modified datetime (To)
+ - name: sort_item
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/ListTokenHoldersPersonalInfoSortItem'
+ description: sort item
+ default: created
+ title: Sort Item
+ description: sort item
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/SortOrder'
+ - type: 'null'
+ description: 'sort order(0: ASC, 1: DESC)'
+ default: 0
+ title: Sort Order
+ description: 'sort order(0: ASC, 1: DESC)'
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: start position
+ title: Offset
+ description: start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: number of set
+ title: Limit
+ description: number of set
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListTokenHoldersPersonalInfoResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ /token/holders/personal_info/history:
+ get:
+ tags:
+ - token_common
+ summary: List All Token Holders Personal Info History
+ description: List personal information historical data
+ operationId: ListTokenHoldersPersonalInfoHistory
+ parameters:
+ - name: account_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: account address
+ title: Account Address
+ description: account address
+ - name: event_type
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/PersonalInfoEventType'
+ - type: 'null'
+ description: event type
+ title: Event Type
+ description: event type
+ - name: block_timestamp_from
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: block timestamp datetime (From)
+ title: Block Timestamp From
+ description: block timestamp datetime (From)
+ - name: block_timestamp_to
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: block timestamp datetime (To)
+ title: Block Timestamp To
+ description: block timestamp datetime (To)
+ - name: created_from
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: created datetime (From)
+ title: Created From
+ description: created datetime (From)
+ - name: created_to
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: created datetime (To)
+ title: Created To
+ description: created datetime (To)
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/SortOrder'
+ - type: 'null'
+ description: 'sort order (0: ASC, 1: DESC)'
+ default: 0
+ title: Sort Order
+ description: 'sort order (0: ASC, 1: DESC)'
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: start position
+ title: Offset
+ description: start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: number of set
+ title: Limit
+ description: number of set
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListTokenHoldersPersonalInfoHistoryResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ /token/holders/{token_address}/collection:
+ post:
+ tags:
+ - token_common
+ summary: Create Token Holders Collection
+ description: Create token holders collection
+ operationId: create_token_holders_collection_token_holders__token_address__collection_post
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ examples:
+ - '0xABCdeF1234567890abcdEf123456789000000000'
+ title: Token Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateTokenHoldersListRequest'
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateTokenHoldersListResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ get:
+ tags:
+ - token_common
+ summary: List All Token Holders Collections
+ operationId: list_all_token_holders_collections_token_holders__token_address__collection_get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: status
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/TokenHolderBatchStatus'
+ - type: 'null'
+ title: Status
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ type: integer
+ maximum: 1
+ minimum: 0
+ description: 0:asc, 1:desc (created)
+ default: 1
+ title: Sort Order
+ description: 0:asc, 1:desc (created)
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Offset
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Limit
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListAllTokenHolderCollectionsResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /token/holders/{token_address}/collection/{list_id}:
+ get:
+ tags:
+ - token_common
+ summary: Retrieve Token Holders Collection
+ description: Retrieve token holders collection
+ operationId:
+ retrieve_token_holders_collection_token_holders__token_address__collection__list_id__get
+ parameters:
+ - name: token_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Token Address
+ - name: list_id
+ in: path
+ required: true
+ schema:
+ type: string
+ description: UUID v4 required
+ examples:
+ - cfd83622-34dc-4efe-a68b-2cc275d3d824
+ title: List Id
+ description: UUID v4 required
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/RetrieveTokenHoldersListResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /blockchain_explorer/block_data:
+ get:
+ tags:
+ - blockchain_explorer
+ summary: '[ibet Blockchain Explorer] List block data'
+ description: |-
+ Returns a list of block data within the specified block number range.
+ The maximum number of search results is 1000.
+ operationId: ListBlockData
+ parameters:
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: start position
+ title: Offset
+ description: start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: number of set
+ title: Limit
+ description: number of set
+ - name: from_block_number
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ title: From Block Number
+ - name: to_block_number
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ title: To Block Number
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/SortOrder'
+ - type: 'null'
+ description: 'sort order(0: ASC, 1: DESC)'
+ default: 0
+ title: Sort Order
+ description: 'sort order(0: ASC, 1: DESC)'
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BlockDataListResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ResponseLimitExceededErrorResponse'
+ /blockchain_explorer/block_data/{block_number}:
+ get:
+ tags:
+ - blockchain_explorer
+ summary: '[ibet Blockchain Explorer] Retrieve block data'
+ description: Returns block data in the specified block number.
+ operationId: GetBlockData
+ parameters:
+ - name: block_number
+ in: path
+ required: true
+ schema:
+ type: integer
+ minimum: 0
+ description: Block number
+ title: Block Number
+ description: Block number
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BlockDataResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /blockchain_explorer/tx_data:
+ get:
+ tags:
+ - blockchain_explorer
+ summary: '[ibet Blockchain Explorer] List tx data'
+ description: |-
+ Returns a list of transactions by various search parameters.
+ The maximum number of search results is 10000.
+ operationId: ListTxData
+ parameters:
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: start position
+ title: Offset
+ description: start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: number of set
+ title: Limit
+ description: number of set
+ - name: block_number
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: block number
+ title: Block Number
+ description: block number
+ - name: from_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: tx from
+ title: From Address
+ description: tx from
+ - name: to_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: tx to
+ title: To Address
+ description: tx to
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TxDataListResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ResponseLimitExceededErrorResponse'
+ /blockchain_explorer/tx_data/{hash}:
+ get:
+ tags:
+ - blockchain_explorer
+ summary: '[ibet Blockchain Explorer] Retrieve transaction data'
+ description: Searching for the transaction by transaction hash
+ operationId: GetTxData
+ parameters:
+ - name: hash
+ in: path
+ required: true
+ schema:
+ type: string
+ description: Transaction hash
+ title: Hash
+ description: Transaction hash
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TxDataResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /freeze_log/accounts:
+ get:
+ tags:
+ - utility
+ summary: List All Accounts
+ description: List all freeze-logging accounts
+ operationId: ListAllFreezeLogAccount
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListAllFreezeLogAccountResponse'
+ post:
+ tags:
+ - utility
+ summary: Create Account
+ description: Create Freeze-Logging Account
+ operationId: CreateFreezeLogAccount
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateFreezeLogAccountRequest'
+ required: true
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/FreezeLogAccountResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /freeze_log/accounts/{account_address}:
+ delete:
+ tags:
+ - utility
+ summary: Delete Account
+ description: Logically delete an freeze-logging account
+ operationId: DeleteFreezeLogAccount
+ parameters:
+ - name: account_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Account Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/FreezeLogAccountResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /freeze_log/accounts/{account_address}/eoa_password:
+ post:
+ tags:
+ - utility
+ summary: Change Eoa Password
+ description: Change Account's EOA Password
+ operationId: ChangeFreezeLogAccountPassword
+ parameters:
+ - name: account_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Account Address
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/FreezeLogAccountChangeEOAPasswordRequest'
+ responses:
+ '200':
+ description: Successful Response
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /freeze_log/logs:
+ post:
+ tags:
+ - utility
+ summary: Record New Log
+ operationId: RecordNewFreezeLog
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/RecordNewFreezeLogRequest'
+ required: true
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/RecordNewFreezeLogResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/SendTransactionErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ title: Response 400 Recordnewfreezelog
+ /freeze_log/logs/{log_index}:
+ post:
+ tags:
+ - utility
+ summary: Update Log
+ operationId: UpdateFreezeLog
+ parameters:
+ - name: log_index
+ in: path
+ required: true
+ schema:
+ type: integer
+ description: Log index
+ title: Log Index
+ description: Log index
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdateFreezeLogRequest'
+ responses:
+ '200':
+ description: Successful Response
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/SendTransactionErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ title: Response 400 Updatefreezelog
+ get:
+ tags:
+ - utility
+ summary: Retrieve Log
+ operationId: RetrieveFreezeLog
+ parameters:
+ - name: log_index
+ in: path
+ required: true
+ schema:
+ type: integer
+ description: Log index
+ title: Log Index
+ description: Log index
+ - name: account_address
+ in: query
+ required: true
+ schema:
+ type: string
+ description: Logging account address
+ title: Account Address
+ description: Logging account address
+ responses:
+ '200':
+ description: Successful Response
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /settlement/dvp/agent/accounts:
+ get:
+ tags:
+ - token_common
+ summary: List All Accounts
+ description: List all DVP-Payment Agent accounts
+ operationId: ListAllDVPAgentAccount
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListAllDVPAgentAccountResponse'
+ post:
+ tags:
+ - token_common
+ summary: Create Account
+ description: Create DVP-Payment Agent Account
+ operationId: CreateDVPAgentAccount
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateDVPAgentAccountRequest'
+ required: true
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DVPAgentAccountResponse'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /settlement/dvp/agent/account/{account_address}:
+ delete:
+ tags:
+ - token_common
+ summary: Delete Account
+ description: Logically delete an DVP-Payment Agent Account
+ operationId: DeleteDVPAgentAccount
+ parameters:
+ - name: account_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Account Address
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DVPAgentAccountResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ /settlement/dvp/agent/account/{account_address}/eoa_password:
+ post:
+ tags:
+ - token_common
+ summary: Change Eoa Password
+ description: Change Account's EOA Password
+ operationId: ChangeDVPAgentAccountPassword
+ parameters:
+ - name: account_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Account Address
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DVPAgentAccountChangeEOAPasswordRequest'
+ responses:
+ '200':
+ description: Successful Response
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ /settlement/dvp/{exchange_address}/deliveries:
+ get:
+ tags:
+ - token_common
+ summary: List All Dvp Deliveries
+ description: List of DVP delivery
+ operationId: ListAllDVPDeliveries
+ parameters:
+ - name: exchange_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Exchange Address
+ - name: token_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: Token address
+ title: Token Address
+ description: Token address
+ - name: seller_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: Seller address
+ title: Seller Address
+ description: Seller address
+ - name: buyer_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: Buyer address
+ title: Buyer Address
+ description: Buyer address
+ - name: agent_address
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: Agent address
+ title: Agent Address
+ description: Agent address
+ - name: valid
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ description: Valid flag
+ title: Valid
+ description: Valid flag
+ - name: status
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/DeliveryStatus'
+ - type: 'null'
+ description: Delivery status
+ title: Status
+ description: Delivery status
+ - name: create_blocktimestamp_from
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ format: date-time
+ - type: 'null'
+ description: Create block timestamp filter(From)
+ title: Create Blocktimestamp From
+ description: Create block timestamp filter(From)
+ - name: create_blocktimestamp_to
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ format: date-time
+ - type: 'null'
+ description: Create block timestamp filter(To)
+ title: Create Blocktimestamp To
+ description: Create block timestamp filter(To)
+ - name: sort_order
+ in: query
+ required: false
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/SortOrder'
+ description: 0:asc, 1:desc
+ default: 1
+ title: Sort Order
+ description: 0:asc, 1:desc
+ - name: offset
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Start position
+ title: Offset
+ description: Start position
+ - name: limit
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: integer
+ minimum: 0
+ - type: 'null'
+ description: Number of set
+ title: Limit
+ description: Number of set
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListAllDVPDeliveriesResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ post:
+ tags:
+ - token_common
+ summary: Create Dvp Delivery
+ operationId: CreateDVPDelivery
+ parameters:
+ - name: exchange_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Exchange Address
+ - name: issuer-address
+ in: header
+ required: true
+ schema:
+ type: string
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateDVPDeliveryRequest'
+ responses:
+ '200':
+ description: Successful Response
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/SendTransactionErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ title: Response 400 Createdvpdelivery
+ /settlement/dvp/{exchange_address}/delivery/{delivery_id}:
+ get:
+ tags:
+ - token_common
+ summary: Retrieve Dvp Delivery
+ description: Retrieve a dvp delivery
+ operationId: RetrieveDVPDelivery
+ parameters:
+ - name: exchange_address
+ in: path
+ required: true
+ schema:
+ type: string
+ description: Exchange Address
+ title: Exchange Address
+ description: Exchange Address
+ - name: delivery_id
+ in: path
+ required: true
+ schema:
+ type: integer
+ description: Delivery Id
+ title: Delivery Id
+ description: Delivery Id
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/RetrieveDVPDeliveryResponse'
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ post:
+ tags:
+ - token_common
+ summary: Update Dvp Delivery
+ operationId: UpdateDVPDelivery
+ parameters:
+ - name: exchange_address
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Exchange Address
+ - name: delivery_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Delivery Id
+ - name: issuer-address
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Issuer-Address
+ - name: eoa-password
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Eoa-Password
+ - name: auth-token
+ in: header
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Auth-Token
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/CancelDVPDeliveryRequest'
+ - $ref: '#/components/schemas/FinishDVPDeliveryRequest'
+ - $ref: '#/components/schemas/AbortDVPDeliveryRequest'
+ title: Data
+ responses:
+ '200':
+ description: Successful Response
+ '404':
+ description: Not Found Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error404Model'
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error422Model'
+ '400':
+ description: Invalid Parameter Error / Send Transaction Error / Contract
+ Revert Error etc
+ content:
+ application/json:
+ schema:
+ anyOf:
+ - $ref: '#/components/schemas/SendTransactionErrorResponse'
+ - $ref: '#/components/schemas/InvalidParameterErrorResponse'
+ title: Response 400 Updatedvpdelivery
+components:
+ schemas:
+ AbortDVPDeliveryRequest:
+ properties:
+ operation_type:
+ type: string
+ enum:
+ - Abort
+ const: Abort
+ title: Operation Type
+ account_address:
+ type: string
+ title: Account Address
+ description: Agent account address
+ eoa_password:
+ type: string
+ title: Eoa Password
+ description: Agent account key file password
+ type: object
+ required:
+ - operation_type
+ - account_address
+ - eoa_password
+ title: AbortDVPDeliveryRequest
+ description: DVP delivery abort schema (REQUEST)
+ AccountAuthTokenRequest:
+ properties:
+ valid_duration:
+ type: integer
+ maximum: 259200.0
+ minimum: 0.0
+ title: Valid Duration
+ type: object
+ title: AccountAuthTokenRequest
+ description: Account Create Auth Token schema (REQUEST)
+ AccountAuthTokenResponse:
+ properties:
+ auth_token:
+ type: string
+ title: Auth Token
+ usage_start:
+ type: string
+ format: date-time
+ title: Usage Start
+ valid_duration:
+ type: integer
+ title: Valid Duration
+ type: object
+ required:
+ - auth_token
+ - usage_start
+ - valid_duration
+ title: AccountAuthTokenResponse
+ description: Account Auth Token schema (RESPONSE)
+ AccountChangeEOAPasswordRequest:
+ properties:
+ old_eoa_password:
+ type: string
+ title: Old Eoa Password
+ eoa_password:
+ type: string
+ title: Eoa Password
+ type: object
+ required:
+ - old_eoa_password
+ - eoa_password
+ title: AccountChangeEOAPasswordRequest
+ description: Account Change EOA Password schema (REQUEST)
+ AccountChangeRSAPassphraseRequest:
+ properties:
+ old_rsa_passphrase:
+ type: string
+ title: Old Rsa Passphrase
+ rsa_passphrase:
+ type: string
+ title: Rsa Passphrase
+ type: object
+ required:
+ - old_rsa_passphrase
+ - rsa_passphrase
+ title: AccountChangeRSAPassphraseRequest
+ description: Account Change RSA Passphrase schema (REQUEST)
+ AccountCreateKeyRequest:
+ properties:
+ eoa_password:
+ type: string
+ title: Eoa Password
+ type: object
+ required:
+ - eoa_password
+ title: AccountCreateKeyRequest
+ description: Account Create Key schema (REQUEST)
+ AccountGenerateRsaKeyRequest:
+ properties:
+ rsa_passphrase:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Rsa Passphrase
+ type: object
+ title: AccountGenerateRsaKeyRequest
+ description: Account Change Rsa Key schema (REQUEST)
+ AccountResponse:
+ properties:
+ issuer_address:
+ type: string
+ title: Issuer Address
+ rsa_public_key:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Rsa Public Key
+ rsa_status:
+ $ref: '#/components/schemas/AccountRsaStatus'
+ is_deleted:
+ type: boolean
+ title: Is Deleted
+ type: object
+ required:
+ - issuer_address
+ - rsa_public_key
+ - rsa_status
+ - is_deleted
+ title: AccountResponse
+ description: Account schema (Response)
+ AccountRsaStatus:
+ type: integer
+ enum:
+ - 0
+ - 1
+ - 2
+ - 3
+ title: AccountRsaStatus
+ description: |-
+ 0:UNSET
+ 1:CREATING
+ 2:CHANGING
+ 3:SET
+ AuthTokenAlreadyExistsErrorCode:
+ type: integer
+ enum:
+ - 3
+ const: 3
+ title: AuthTokenAlreadyExistsErrorCode
+ AuthTokenAlreadyExistsErrorMetainfo:
+ properties:
+ code:
+ allOf:
+ - $ref: '#/components/schemas/AuthTokenAlreadyExistsErrorCode'
+ examples:
+ - 3
+ title:
+ type: string
+ title: Title
+ examples:
+ - AuthTokenAlreadyExistsError
+ type: object
+ required:
+ - code
+ - title
+ title: AuthTokenAlreadyExistsErrorMetainfo
+ AuthTokenAlreadyExistsErrorResponse:
+ properties:
+ meta:
+ $ref: '#/components/schemas/AuthTokenAlreadyExistsErrorMetainfo'
+ detail:
+ type: string
+ title: Detail
+ type: object
+ required:
+ - meta
+ - detail
+ title: AuthTokenAlreadyExistsErrorResponse
+ AuthorizationErrorCode:
+ type: integer
+ enum:
+ - 1
+ const: 1
+ title: AuthorizationErrorCode
+ AuthorizationErrorMetainfo:
+ properties:
+ code:
+ allOf:
+ - $ref: '#/components/schemas/AuthorizationErrorCode'
+ examples:
+ - 1
+ title:
+ type: string
+ title: Title
+ examples:
+ - AuthorizationError
+ type: object
+ required:
+ - code
+ - title
+ title: AuthorizationErrorMetainfo
+ AuthorizationErrorResponse:
+ properties:
+ meta:
+ $ref: '#/components/schemas/AuthorizationErrorMetainfo'
+ detail:
+ type: string
+ title: Detail
+ type: object
+ required:
+ - meta
+ - detail
+ title: AuthorizationErrorResponse
+ BatchIssueRedeemProcessedMetaInfo:
+ properties:
+ category:
+ $ref: '#/components/schemas/BatchIssueRedeemProcessingCategory'
+ upload_id:
+ type: string
+ title: Upload Id
+ error_data_id:
+ items:
+ type: integer
+ type: array
+ title: Error Data Id
+ token_address:
+ type: string
+ title: Token Address
+ token_type:
+ $ref: '#/components/schemas/TokenType'
+ type: object
+ required:
+ - category
+ - upload_id
+ - error_data_id
+ - token_address
+ - token_type
+ title: BatchIssueRedeemProcessedMetaInfo
+ BatchIssueRedeemProcessedNotification:
+ properties:
+ notice_id:
+ type: string
+ title: Notice Id
+ issuer_address:
+ type: string
+ title: Issuer Address
+ priority:
+ type: integer
+ title: Priority
+ notice_code:
+ type: integer
+ maximum: 3.0
+ minimum: 0.0
+ title: Notice Code
+ description: |2-
+ - 0: All records successfully processed
+ - 1: Issuer does not exist
+ - 2: Failed to decode keyfile
+ - 3: Some records are failed to send transaction
+ created:
+ type: string
+ title: Created
+ notice_type:
+ type: string
+ enum:
+ - BatchIssueProcessed
+ const: BatchIssueProcessed
+ title: Notice Type
+ metainfo:
+ $ref: '#/components/schemas/BatchIssueRedeemProcessedMetaInfo'
+ type: object
+ required:
+ - notice_id
+ - issuer_address
+ - priority
+ - notice_code
+ - created
+ - notice_type
+ - metainfo
+ title: BatchIssueRedeemProcessedNotification
+ BatchIssueRedeemProcessingCategory:
+ type: string
+ enum:
+ - Issue
+ - Redeem
+ title: BatchIssueRedeemProcessingCategory
+ description: Batch Issue/Redeem Category
+ BatchIssueRedeemUpload:
+ properties:
+ batch_id:
+ type: string
+ title: Batch Id
+ description: UUID v4 required
+ issuer_address:
+ type: string
+ title: Issuer Address
+ token_type:
+ $ref: '#/components/schemas/TokenType'
+ token_address:
+ type: string
+ title: Token Address
+ processed:
+ type: boolean
+ title: Processed
+ created:
+ type: string
+ title: Created
+ type: object
+ required:
+ - batch_id
+ - issuer_address
+ - token_type
+ - token_address
+ - processed
+ - created
+ title: BatchIssueRedeemUpload
+ description: Batch issue/redeem Upload
+ examples:
+ - batch_id: cfd83622-34dc-4efe-a68b-2cc275d3d824
+ created: '2022-09-02T19:49:33.370874+09:00'
+ issuer_address: '0x0000000000000000000000000000000000000000'
+ processed: true
+ token_address: '0x0000000000000000000000000000000000000000'
+ token_type: Bond
+ BatchIssueRedeemUploadIdResponse:
+ properties:
+ batch_id:
+ type: string
+ title: Batch Id
+ type: object
+ required:
+ - batch_id
+ title: BatchIssueRedeemUploadIdResponse
+ description: Batch issue/redeem upload id (RESPONSE)
+ BatchRegisterPersonalInfoErrorMetaInfo:
+ properties:
+ upload_id:
+ type: string
+ title: Upload Id
+ error_registration_id:
+ items:
+ type: integer
+ type: array
+ title: Error Registration Id
+ type: object
+ required:
+ - upload_id
+ - error_registration_id
+ title: BatchRegisterPersonalInfoErrorMetaInfo
+ BatchRegisterPersonalInfoErrorNotification:
+ properties:
+ notice_id:
+ type: string
+ title: Notice Id
+ issuer_address:
+ type: string
+ title: Issuer Address
+ priority:
+ type: integer
+ title: Priority
+ notice_code:
+ type: integer
+ maximum: 1.0
+ minimum: 0.0
+ title: Notice Code
+ description: |2
+ - 0: Issuer does not exist
+ - 1: Failed to send transaction
+ created:
+ type: string
+ title: Created
+ notice_type:
+ type: string
+ enum:
+ - BatchRegisterPersonalInfoError
+ const: BatchRegisterPersonalInfoError
+ title: Notice Type
+ metainfo:
+ $ref: '#/components/schemas/BatchRegisterPersonalInfoErrorMetaInfo'
+ type: object
+ required:
+ - notice_id
+ - issuer_address
+ - priority
+ - notice_code
+ - created
+ - notice_type
+ - metainfo
+ title: BatchRegisterPersonalInfoErrorNotification
+ BatchRegisterPersonalInfoResult:
+ properties:
+ status:
+ type: integer
+ title: Status
+ account_address:
+ type: string
+ title: Account Address
+ key_manager:
+ type: string
+ title: Key Manager
+ name:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Name
+ postal_code:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Postal Code
+ address:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Address
+ email:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Email
+ birth:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Birth
+ is_corporate:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Is Corporate
+ tax_category:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Tax Category
+ type: object
+ required:
+ - status
+ - account_address
+ - key_manager
+ - name
+ - postal_code
+ - address
+ - email
+ - birth
+ - is_corporate
+ - tax_category
+ title: BatchRegisterPersonalInfoResult
+ description: Result of Creating Batch Register PersonalInfo schema (RESPONSE)
+ BatchRegisterPersonalInfoUploadResponse:
+ properties:
+ batch_id:
+ type: string
+ title: Batch Id
+ description: UUID v4 required
+ status:
+ $ref: '#/components/schemas/BatchRegisterPersonalInfoUploadStatus'
+ created:
+ type: string
+ title: Created
+ type: object
+ required:
+ - batch_id
+ - status
+ - created
+ title: BatchRegisterPersonalInfoUploadResponse
+ description: Batch Register PersonalInfo schema (RESPONSE)
+ examples:
+ - batch_id: cfd83622-34dc-4efe-a68b-2cc275d3d824
+ created: '2022-09-02T19:49:33.370874+09:00'
+ status: pending
+ BatchRegisterPersonalInfoUploadStatus:
+ type: string
+ enum:
+ - pending
+ - done
+ - failed
+ title: BatchRegisterPersonalInfoUploadStatus
+ description: Batch Register PersonalInfo Upload Status
+ BlockData:
+ properties:
+ number:
+ type: integer
+ minimum: 0.0
+ title: Number
+ description: Block number
+ hash:
+ type: string
+ title: Hash
+ description: Block hash
+ transactions:
+ items:
+ type: string
+ type: array
+ title: Transactions
+ description: Transaction list
+ timestamp:
+ type: integer
+ title: Timestamp
+ gas_limit:
+ type: integer
+ title: Gas Limit
+ gas_used:
+ type: integer
+ title: Gas Used
+ size:
+ type: integer
+ minimum: 0.0
+ title: Size
+ type: object
+ required:
+ - number
+ - hash
+ - transactions
+ - timestamp
+ - gas_limit
+ - gas_used
+ - size
+ title: BlockData
+ BlockDataDetail:
+ properties:
+ number:
+ type: integer
+ minimum: 0.0
+ title: Number
+ description: Block number
+ parent_hash:
+ type: string
+ title: Parent Hash
+ sha3_uncles:
+ type: string
+ title: Sha3 Uncles
+ miner:
+ type: string
+ title: Miner
+ state_root:
+ type: string
+ title: State Root
+ transactions_root:
+ type: string
+ title: Transactions Root
+ receipts_root:
+ type: string
+ title: Receipts Root
+ logs_bloom:
+ type: string
+ title: Logs Bloom
+ difficulty:
+ type: integer
+ title: Difficulty
+ gas_limit:
+ type: integer
+ title: Gas Limit
+ gas_used:
+ type: integer
+ title: Gas Used
+ timestamp:
+ type: integer
+ title: Timestamp
+ proof_of_authority_data:
+ type: string
+ title: Proof Of Authority Data
+ mix_hash:
+ type: string
+ title: Mix Hash
+ nonce:
+ type: string
+ title: Nonce
+ hash:
+ type: string
+ title: Hash
+ description: Block hash
+ size:
+ type: integer
+ minimum: 0.0
+ title: Size
+ transactions:
+ items:
+ type: string
+ type: array
+ title: Transactions
+ description: Transaction list
+ type: object
+ required:
+ - number
+ - parent_hash
+ - sha3_uncles
+ - miner
+ - state_root
+ - transactions_root
+ - receipts_root
+ - logs_bloom
+ - difficulty
+ - gas_limit
+ - gas_used
+ - timestamp
+ - proof_of_authority_data
+ - mix_hash
+ - nonce
+ - hash
+ - size
+ - transactions
+ title: BlockDataDetail
+ BlockDataListResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ block_data:
+ items:
+ $ref: '#/components/schemas/BlockData'
+ type: array
+ title: Block Data
+ type: object
+ required:
+ - result_set
+ - block_data
+ title: BlockDataListResponse
+ BlockDataResponse:
+ allOf:
+ - $ref: '#/components/schemas/BlockDataDetail'
+ title: BlockDataResponse
+ BlockNumberResponse:
+ properties:
+ block_number:
+ type: integer
+ title: Block Number
+ type: object
+ required:
+ - block_number
+ title: BlockNumberResponse
+ description: Block Number schema (Response)
+ BulkTransferErrorMetaInfo:
+ properties:
+ upload_id:
+ type: string
+ title: Upload Id
+ token_type:
+ $ref: '#/components/schemas/TokenType'
+ error_transfer_id:
+ items:
+ type: integer
+ type: array
+ title: Error Transfer Id
+ type: object
+ required:
+ - upload_id
+ - token_type
+ - error_transfer_id
+ title: BulkTransferErrorMetaInfo
+ BulkTransferErrorNotification:
+ properties:
+ notice_id:
+ type: string
+ title: Notice Id
+ issuer_address:
+ type: string
+ title: Issuer Address
+ priority:
+ type: integer
+ title: Priority
+ notice_code:
+ type: integer
+ maximum: 2.0
+ minimum: 0.0
+ title: Notice Code
+ description: |2
+ - 0: Issuer does not exist
+ - 1: Could not get the private key of the issuer
+ - 2: Failed to send transaction
+ created:
+ type: string
+ title: Created
+ notice_type:
+ type: string
+ enum:
+ - BulkTransferError
+ const: BulkTransferError
+ title: Notice Type
+ metainfo:
+ $ref: '#/components/schemas/BulkTransferErrorMetaInfo'
+ type: object
+ required:
+ - notice_id
+ - issuer_address
+ - priority
+ - notice_code
+ - created
+ - notice_type
+ - metainfo
+ title: BulkTransferErrorNotification
+ BulkTransferResponse:
+ properties:
+ upload_id:
+ type: string
+ title: Upload Id
+ description: Upload id
+ issuer_address:
+ type: string
+ title: Issuer Address
+ description: Issuer account address
+ token_address:
+ type: string
+ title: Token Address
+ description: Token address
+ token_type:
+ allOf:
+ - $ref: '#/components/schemas/TokenType'
+ description: Token type
+ from_address:
+ type: string
+ title: From Address
+ description: Transfer source address
+ to_address:
+ type: string
+ title: To Address
+ description: Transfer destination address
+ amount:
+ type: integer
+ title: Amount
+ description: Transfer amount
+ status:
+ type: integer
+ title: Status
+ description: Transfer status
+ transaction_error_code:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Transaction Error Code
+ description: Transfer error code
+ transaction_error_message:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Transaction Error Message
+ description: Transfer error message
+ type: object
+ required:
+ - upload_id
+ - issuer_address
+ - token_address
+ - token_type
+ - from_address
+ - to_address
+ - amount
+ - status
+ - transaction_error_code
+ - transaction_error_message
+ title: BulkTransferResponse
+ description: bulk transfer data
+ BulkTransferUploadIdResponse:
+ properties:
+ upload_id:
+ type: string
+ title: Upload Id
+ description: Upload id
+ type: object
+ required:
+ - upload_id
+ title: BulkTransferUploadIdResponse
+ description: bulk transfer upload id
+ BulkTransferUploadResponse:
+ properties:
+ upload_id:
+ type: string
+ title: Upload Id
+ description: Upload id
+ issuer_address:
+ type: string
+ title: Issuer Address
+ description: Issuer account address
+ token_type:
+ allOf:
+ - $ref: '#/components/schemas/TokenType'
+ description: Token type
+ transaction_compression:
+ type: boolean
+ title: Transaction Compression
+ description: Transaction compression mode
+ status:
+ type: integer
+ title: Status
+ description: Processing status
+ created:
+ type: string
+ title: Created
+ description: Upload created datetime (ISO8601)
+ type: object
+ required:
+ - upload_id
+ - issuer_address
+ - token_type
+ - transaction_compression
+ - status
+ - created
+ title: BulkTransferUploadResponse
+ description: bulk transfer upload
+ CancelDVPDeliveryRequest:
+ properties:
+ operation_type:
+ type: string
+ enum:
+ - Cancel
+ const: Cancel
+ title: Operation Type
+ type: object
+ required:
+ - operation_type
+ title: CancelDVPDeliveryRequest
+ description: DVP delivery cancel schema (REQUEST)
+ ContractRevertErrorCode:
+ type: integer
+ enum:
+ - 0
+ - 100001
+ - 100002
+ - 100101
+ - 100102
+ - 110001
+ - 110002
+ - 110101
+ - 110102
+ - 110201
+ - 110202
+ - 110301
+ - 110401
+ - 110402
+ - 110501
+ - 110502
+ - 110503
+ - 110504
+ - 110601
+ - 110701
+ - 110702
+ - 110801
+ - 110802
+ - 110901
+ - 110902
+ - 111001
+ - 111002
+ - 111101
+ - 111102
+ - 111201
+ - 120001
+ - 120002
+ - 120101
+ - 120102
+ - 120201
+ - 120202
+ - 120301
+ - 120401
+ - 120402
+ - 120501
+ - 120502
+ - 120503
+ - 120601
+ - 120701
+ - 120702
+ - 120801
+ - 120802
+ - 120901
+ - 120902
+ - 121001
+ - 121002
+ - 121101
+ - 121102
+ - 121201
+ - 130001
+ - 130101
+ - 130102
+ - 130201
+ - 130202
+ - 130203
+ - 130301
+ - 130401
+ - 130501
+ - 130502
+ - 140001
+ - 140101
+ - 140102
+ - 140201
+ - 140202
+ - 140203
+ - 140301
+ - 140401
+ - 140402
+ - 150001
+ - 150101
+ - 150201
+ - 150202
+ - 150301
+ - 200001
+ - 210001
+ - 210101
+ - 210102
+ - 210103
+ - 210104
+ - 210201
+ - 210202
+ - 210203
+ - 210204
+ - 210301
+ - 210302
+ - 210401
+ - 210402
+ - 210403
+ - 210501
+ - 210502
+ - 210503
+ - 210504
+ - 210601
+ - 220001
+ - 230001
+ - 230002
+ - 230003
+ - 230101
+ - 230102
+ - 230103
+ - 230104
+ - 230201
+ - 230202
+ - 230203
+ - 230204
+ - 230301
+ - 240001
+ - 240002
+ - 240003
+ - 240101
+ - 240102
+ - 240103
+ - 240104
+ - 240201
+ - 240202
+ - 240203
+ - 240204
+ - 240205
+ - 240301
+ - 240302
+ - 240303
+ - 240304
+ - 240401
+ - 250001
+ - 260001
+ - 260002
+ - 260003
+ - 260004
+ - 260101
+ - 260102
+ - 260103
+ - 260104
+ - 260201
+ - 260202
+ - 260203
+ - 260204
+ - 260205
+ - 260206
+ - 260301
+ - 260302
+ - 260303
+ - 260304
+ - 260305
+ - 260306
+ - 260401
+ - 260402
+ - 260403
+ - 260404
+ - 260501
+ - 300001
+ - 300101
+ - 300201
+ - 300301
+ - 300401
+ - 300501
+ - 400001
+ - 400002
+ - 500001
+ - 500101
+ - 600001
+ - 600002
+ - 610001
+ - 610011
+ - 620001
+ title: ContractRevertErrorCode
+ ContractRevertErrorMetainfo:
+ properties:
+ code:
+ allOf:
+ - $ref: '#/components/schemas/ContractRevertErrorCode'
+ examples:
+ - 0
+ title:
+ type: string
+ title: Title
+ examples:
+ - ContractRevertError
+ type: object
+ required:
+ - code
+ - title
+ title: ContractRevertErrorMetainfo
+ ContractRevertErrorResponse:
+ properties:
+ meta:
+ $ref: '#/components/schemas/ContractRevertErrorMetainfo'
+ detail:
+ type: string
+ title: Detail
+ type: object
+ required:
+ - meta
+ - detail
+ title: ContractRevertErrorResponse
+ description: |-
+ Revert error occurs from smart-contract
+
+ - Error code: https://github.com/BoostryJP/ibet-SmartContract/blob/master/docs/Errors.md
+ - If contract doesn't throw error code, 0 is returned.
+ CreateDVPAgentAccountRequest:
+ properties:
+ eoa_password:
+ type: string
+ title: Eoa Password
+ description: EOA keyfile password
+ type: object
+ required:
+ - eoa_password
+ title: CreateDVPAgentAccountRequest
+ description: DVP agent account create schema (REQUEST)
+ CreateDVPDeliveryRequest:
+ properties:
+ token_address:
+ type: string
+ title: Token Address
+ buyer_address:
+ type: string
+ title: Buyer Address
+ amount:
+ type: integer
+ maximum: 1000000000000.0
+ minimum: 1.0
+ title: Amount
+ agent_address:
+ type: string
+ title: Agent Address
+ data:
+ type: string
+ title: Data
+ type: object
+ required:
+ - token_address
+ - buyer_address
+ - amount
+ - agent_address
+ - data
+ title: CreateDVPDeliveryRequest
+ description: DVP delivery create schema (REQUEST)
+ CreateFreezeLogAccountRequest:
+ properties:
+ eoa_password:
+ type: string
+ title: Eoa Password
+ description: EOA keyfile password
+ type: object
+ required:
+ - eoa_password
+ title: CreateFreezeLogAccountRequest
+ description: Freeze-Logging account create schema (REQUEST)
+ CreateLedgerInfoMetaInfo:
+ properties:
+ token_address:
+ type: string
+ title: Token Address
+ token_type:
+ $ref: '#/components/schemas/TokenType'
+ ledger_id:
+ type: integer
+ title: Ledger Id
+ type: object
+ required:
+ - token_address
+ - token_type
+ - ledger_id
+ title: CreateLedgerInfoMetaInfo
+ CreateLedgerInfoNotification:
+ properties:
+ notice_id:
+ type: string
+ title: Notice Id
+ issuer_address:
+ type: string
+ title: Issuer Address
+ priority:
+ type: integer
+ title: Priority
+ notice_code:
+ type: integer
+ maximum: 0.0
+ minimum: 0.0
+ title: Notice Code
+ description: " - 0: Created ledger info successfully\n"
+ created:
+ type: string
+ title: Created
+ notice_type:
+ type: string
+ enum:
+ - CreateLedgerInfo
+ const: CreateLedgerInfo
+ title: Notice Type
+ metainfo:
+ $ref: '#/components/schemas/CreateLedgerInfoMetaInfo'
+ type: object
+ required:
+ - notice_id
+ - issuer_address
+ - priority
+ - notice_code
+ - created
+ - notice_type
+ - metainfo
+ title: CreateLedgerInfoNotification
+ CreateTokenHoldersListRequest:
+ properties:
+ list_id:
+ type: string
+ title: List Id
+ description: UUID v4 required
+ block_number:
+ type: integer
+ minimum: 1.0
+ title: Block Number
+ type: object
+ required:
+ - list_id
+ - block_number
+ title: CreateTokenHoldersListRequest
+ description: Create Token Holders List schema (REQUEST)
+ examples:
+ - block_number: 765
+ list_id: cfd83622-34dc-4efe-a68b-2cc275d3d824
+ CreateTokenHoldersListResponse:
+ properties:
+ list_id:
+ type: string
+ title: List Id
+ description: UUID v4 required
+ status:
+ $ref: '#/components/schemas/TokenHolderBatchStatus'
+ type: object
+ required:
+ - list_id
+ - status
+ title: CreateTokenHoldersListResponse
+ description: Create Token Holders List schema (RESPONSE)
+ examples:
+ - list_id: cfd83622-34dc-4efe-a68b-2cc275d3d824
+ status: pending
+ CreateUpdateLedgerDetailsDataRequest:
+ properties:
+ name:
+ anyOf:
+ - type: string
+ maxLength: 200
+ - type: 'null'
+ title: Name
+ address:
+ anyOf:
+ - type: string
+ maxLength: 200
+ - type: 'null'
+ title: Address
+ amount:
+ anyOf:
+ - type: integer
+ maximum: 1000000000000.0
+ minimum: 0.0
+ - type: 'null'
+ title: Amount
+ price:
+ anyOf:
+ - type: integer
+ maximum: 1000000000000.0
+ minimum: 0.0
+ - type: 'null'
+ title: Price
+ balance:
+ anyOf:
+ - type: integer
+ maximum: 9.223372036854776e+18
+ minimum: 0.0
+ - type: 'null'
+ title: Balance
+ acquisition_date:
+ anyOf:
+ - type: string
+ maxLength: 10
+ minLength: 10
+ - type: 'null'
+ title: Acquisition Date
+ description: YYYY/MM/DD
+ type: object
+ title: CreateUpdateLedgerDetailsDataRequest
+ description: Create or Update Ledger Details Data Structure schema (Request)
+ CreateUpdateLedgerDetailsDataTemplateRequest:
+ properties:
+ type:
+ $ref: '#/components/schemas/LedgerDetailsDataType'
+ source:
+ anyOf:
+ - type: string
+ maxLength: 42
+ - type: 'null'
+ title: Source
+ type: object
+ required:
+ - type
+ title: CreateUpdateLedgerDetailsDataTemplateRequest
+ description: Create or Update Ledger Details Data Template schema (Request)
+ CreateUpdateLedgerDetailsTemplateRequest:
+ properties:
+ token_detail_type:
+ type: string
+ maxLength: 100
+ title: Token Detail Type
+ headers:
+ anyOf:
+ - items:
+ type: object
+ type: array
+ - type: 'null'
+ title: Headers
+ data:
+ $ref: '#/components/schemas/CreateUpdateLedgerDetailsDataTemplateRequest'
+ footers:
+ anyOf:
+ - items:
+ type: object
+ type: array
+ - type: 'null'
+ title: Footers
+ type: object
+ required:
+ - token_detail_type
+ - data
+ title: CreateUpdateLedgerDetailsTemplateRequest
+ description: Create or Update Ledger Details Template schema (Request)
+ CreateUpdateLedgerTemplateRequest:
+ properties:
+ token_name:
+ type: string
+ maxLength: 200
+ title: Token Name
+ headers:
+ anyOf:
+ - items:
+ type: object
+ type: array
+ - type: 'null'
+ title: Headers
+ details:
+ items:
+ $ref: '#/components/schemas/CreateUpdateLedgerDetailsTemplateRequest'
+ type: array
+ title: Details
+ footers:
+ anyOf:
+ - items:
+ type: object
+ type: array
+ - type: 'null'
+ title: Footers
+ type: object
+ required:
+ - token_name
+ - details
+ title: CreateUpdateLedgerTemplateRequest
+ description: Create or Update Ledger Template schema (Request)
+ DVPAgentAccountChangeEOAPasswordRequest:
+ properties:
+ old_eoa_password:
+ type: string
+ title: Old Eoa Password
+ description: EOA keyfile password (old)
+ eoa_password:
+ type: string
+ title: Eoa Password
+ description: EOA keyfile password (new)
+ type: object
+ required:
+ - old_eoa_password
+ - eoa_password
+ title: DVPAgentAccountChangeEOAPasswordRequest
+ description: DVP agent account change EOA password schema (REQUEST)
+ DVPAgentAccountResponse:
+ properties:
+ account_address:
+ type: string
+ title: Account Address
+ is_deleted:
+ type: boolean
+ title: Is Deleted
+ type: object
+ required:
+ - account_address
+ - is_deleted
+ title: DVPAgentAccountResponse
+ description: DVP agent account reference schema (RESPONSE)
+ DeliveryStatus:
+ type: integer
+ enum:
+ - 0
+ - 1
+ - 2
+ - 3
+ - 4
+ title: DeliveryStatus
+ description: DVP Delivery Status
+ DownloadFileResponse:
+ properties:
+ file_id:
+ type: string
+ title: File Id
+ issuer_address:
+ type: string
+ title: Issuer Address
+ relation:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Relation
+ file_name:
+ type: string
+ title: File Name
+ content:
+ type: string
+ title: Content
+ description: Base64-encoded content
+ content_size:
+ type: integer
+ title: Content Size
+ description:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Description
+ label:
+ type: string
+ title: Label
+ type: object
+ required:
+ - file_id
+ - issuer_address
+ - relation
+ - file_name
+ - content
+ - content_size
+ - description
+ - label
+ title: DownloadFileResponse
+ description: Download File schema (Response)
+ E2EEResponse:
+ properties:
+ public_key:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Public Key
+ type: object
+ required:
+ - public_key
+ title: E2EEResponse
+ description: E2EE schema (Response)
+ E2EMessagingAccountChangeEOAPasswordRequest:
+ properties:
+ old_eoa_password:
+ type: string
+ title: Old Eoa Password
+ eoa_password:
+ type: string
+ title: Eoa Password
+ type: object
+ required:
+ - old_eoa_password
+ - eoa_password
+ title: E2EMessagingAccountChangeEOAPasswordRequest
+ description: E2E Messaging Account Change EOA Password schema (REQUEST)
+ E2EMessagingAccountChangeRSAPassphraseRequest:
+ properties:
+ old_rsa_passphrase:
+ type: string
+ title: Old Rsa Passphrase
+ rsa_passphrase:
+ type: string
+ title: Rsa Passphrase
+ type: object
+ required:
+ - old_rsa_passphrase
+ - rsa_passphrase
+ title: E2EMessagingAccountChangeRSAPassphraseRequest
+ description: E2E Messaging Account Change RSA Passphrase schema (REQUEST)
+ E2EMessagingAccountCreateRequest:
+ properties:
+ eoa_password:
+ type: string
+ title: Eoa Password
+ rsa_passphrase:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Rsa Passphrase
+ rsa_key_generate_interval:
+ anyOf:
+ - type: integer
+ maximum: 10000.0
+ minimum: 0.0
+ - type: 'null'
+ title: Rsa Key Generate Interval
+ description: 0 disables auto-generate(Unit is hour)
+ default: 24
+ rsa_generation:
+ anyOf:
+ - type: integer
+ maximum: 100.0
+ minimum: 0.0
+ - type: 'null'
+ title: Rsa Generation
+ description: 0 disables generation
+ default: 7
+ type: object
+ required:
+ - eoa_password
+ title: E2EMessagingAccountCreateRequest
+ description: E2E Messaging Account Create schema (REQUEST)
+ E2EMessagingAccountResponse:
+ properties:
+ account_address:
+ type: string
+ title: Account Address
+ rsa_key_generate_interval:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Rsa Key Generate Interval
+ rsa_generation:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Rsa Generation
+ rsa_public_key:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Rsa Public Key
+ is_deleted:
+ type: boolean
+ title: Is Deleted
+ type: object
+ required:
+ - account_address
+ - rsa_key_generate_interval
+ - rsa_generation
+ - rsa_public_key
+ - is_deleted
+ title: E2EMessagingAccountResponse
+ description: E2E Messaging Account schema (Response)
+ E2EMessagingAccountUpdateRsaKeyRequest:
+ properties:
+ rsa_key_generate_interval:
+ anyOf:
+ - type: integer
+ maximum: 10000.0
+ minimum: 0.0
+ - type: 'null'
+ title: Rsa Key Generate Interval
+ description: 0 disables auto-generate(Unit is hour)
+ default: 24
+ rsa_generation:
+ anyOf:
+ - type: integer
+ maximum: 100.0
+ minimum: 0.0
+ - type: 'null'
+ title: Rsa Generation
+ description: 0 disables generation
+ default: 7
+ type: object
+ title: E2EMessagingAccountUpdateRsaKeyRequest
+ description: E2E Messaging Account Rsa Key Update schema (REQUEST)
+ E2EMessagingResponse:
+ properties:
+ id:
+ type: integer
+ title: Id
+ from_address:
+ type: string
+ title: From Address
+ to_address:
+ type: string
+ title: To Address
+ type:
+ type: string
+ title: Type
+ message:
+ anyOf:
+ - type: string
+ - type: object
+ - items: {}
+ type: array
+ title: Message
+ send_timestamp:
+ type: string
+ format: date-time
+ title: Send Timestamp
+ type: object
+ required:
+ - id
+ - from_address
+ - to_address
+ - type
+ - message
+ - send_timestamp
+ title: E2EMessagingResponse
+ description: E2E Messaging schema (Response)
+ Error401MetaModel:
+ properties:
+ code:
+ type: integer
+ title: Code
+ examples:
+ - 1
+ title:
+ type: string
+ title: Title
+ examples:
+ - AuthorizationError
+ type: object
+ required:
+ - code
+ - title
+ title: Error401MetaModel
+ Error401Model:
+ properties:
+ meta:
+ $ref: '#/components/schemas/Error401MetaModel'
+ detail:
+ type: string
+ title: Detail
+ type: object
+ required:
+ - meta
+ - detail
+ title: Error401Model
+ Error404MetaModel:
+ properties:
+ code:
+ type: integer
+ title: Code
+ examples:
+ - 1
+ title:
+ type: string
+ title: Title
+ examples:
+ - NotFound
+ type: object
+ required:
+ - code
+ - title
+ title: Error404MetaModel
+ Error404Model:
+ properties:
+ meta:
+ $ref: '#/components/schemas/Error404MetaModel'
+ detail:
+ type: string
+ title: Detail
+ type: object
+ required:
+ - meta
+ - detail
+ title: Error404Model
+ Error422DetailModel:
+ properties:
+ loc:
+ items:
+ type: string
+ type: array
+ title: Loc
+ examples:
+ - - header
+ - issuer-address
+ msg:
+ type: string
+ title: Msg
+ examples:
+ - field required
+ type:
+ type: string
+ title: Type
+ examples:
+ - value_error.missing
+ type: object
+ required:
+ - loc
+ - msg
+ - type
+ title: Error422DetailModel
+ Error422MetaModel:
+ properties:
+ code:
+ type: integer
+ title: Code
+ examples:
+ - 1
+ title:
+ type: string
+ title: Title
+ examples:
+ - RequestValidationError
+ type: object
+ required:
+ - code
+ - title
+ title: Error422MetaModel
+ Error422Model:
+ properties:
+ meta:
+ $ref: '#/components/schemas/Error422MetaModel'
+ detail:
+ items:
+ $ref: '#/components/schemas/Error422DetailModel'
+ type: array
+ title: Detail
+ type: object
+ required:
+ - meta
+ - detail
+ title: Error422Model
+ FileResponse:
+ properties:
+ file_id:
+ type: string
+ title: File Id
+ issuer_address:
+ type: string
+ title: Issuer Address
+ relation:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Relation
+ file_name:
+ type: string
+ title: File Name
+ content_size:
+ type: integer
+ title: Content Size
+ description:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Description
+ label:
+ type: string
+ title: Label
+ created:
+ type: string
+ format: date-time
+ title: Created
+ type: object
+ required:
+ - file_id
+ - issuer_address
+ - relation
+ - file_name
+ - content_size
+ - description
+ - label
+ - created
+ title: FileResponse
+ description: File schema (Response)
+ FinishDVPDeliveryRequest:
+ properties:
+ operation_type:
+ type: string
+ enum:
+ - Finish
+ const: Finish
+ title: Operation Type
+ account_address:
+ type: string
+ title: Account Address
+ description: Agent account address
+ eoa_password:
+ type: string
+ title: Eoa Password
+ description: Agent account key file password
+ type: object
+ required:
+ - operation_type
+ - account_address
+ - eoa_password
+ title: FinishDVPDeliveryRequest
+ description: DVP delivery finish schema (REQUEST)
+ ForceUnlockRequest:
+ properties:
+ token_address:
+ type: string
+ title: Token Address
+ description: Token address
+ lock_address:
+ type: string
+ title: Lock Address
+ description: Lock address
+ recipient_address:
+ type: string
+ title: Recipient Address
+ description: Recipient address
+ value:
+ type: integer
+ exclusiveMinimum: 0.0
+ title: Value
+ description: Unlock amount
+ type: object
+ required:
+ - token_address
+ - lock_address
+ - recipient_address
+ - value
+ title: ForceUnlockRequest
+ FreezeLogAccountChangeEOAPasswordRequest:
+ properties:
+ old_eoa_password:
+ type: string
+ title: Old Eoa Password
+ description: EOA keyfile password (old)
+ eoa_password:
+ type: string
+ title: Eoa Password
+ description: EOA keyfile password (new)
+ type: object
+ required:
+ - old_eoa_password
+ - eoa_password
+ title: FreezeLogAccountChangeEOAPasswordRequest
+ description: Freeze-Logging account change EOA password schema (REQUEST)
+ FreezeLogAccountResponse:
+ properties:
+ account_address:
+ type: string
+ title: Account Address
+ is_deleted:
+ type: boolean
+ title: Is Deleted
+ type: object
+ required:
+ - account_address
+ - is_deleted
+ title: FreezeLogAccountResponse
+ description: Freeze-logging account reference schema (RESPONSE)
+ GetBatchIssueRedeemResponse:
+ properties:
+ processed:
+ type: boolean
+ title: Processed
+ results:
+ items:
+ $ref: '#/components/schemas/GetBatchIssueRedeemResult'
+ type: array
+ title: Results
+ type: object
+ required:
+ - processed
+ - results
+ title: GetBatchIssueRedeemResponse
+ description: Get Batch issue/redeem upload schema (RESPONSE)
+ GetBatchIssueRedeemResult:
+ properties:
+ account_address:
+ type: string
+ title: Account Address
+ amount:
+ type: integer
+ title: Amount
+ status:
+ type: integer
+ title: Status
+ personal_information:
+ $ref: '#/components/schemas/PersonalInfo'
+ type: object
+ required:
+ - account_address
+ - amount
+ - status
+ - personal_information
+ title: GetBatchIssueRedeemResult
+ description: Result of Creating Batch issue/redeem schema (RESPONSE)
+ GetBatchRegisterPersonalInfoResponse:
+ properties:
+ status:
+ $ref: '#/components/schemas/BatchRegisterPersonalInfoUploadStatus'
+ results:
+ items:
+ $ref: '#/components/schemas/BatchRegisterPersonalInfoResult'
+ type: array
+ title: Results
+ type: object
+ required:
+ - status
+ - results
+ title: GetBatchRegisterPersonalInfoResponse
+ description: Get Batch Register PersonalInfo schema (RESPONSE)
+ HTTPValidationError:
+ properties:
+ detail:
+ items:
+ $ref: '#/components/schemas/ValidationError'
+ type: array
+ title: Detail
+ type: object
+ title: HTTPValidationError
+ HolderCountResponse:
+ properties:
+ count:
+ type: integer
+ title: Count
+ type: object
+ required:
+ - count
+ title: HolderCountResponse
+ description: Holder count schema (Response)
+ HolderResponse:
+ properties:
+ account_address:
+ type: string
+ title: Account Address
+ personal_information:
+ $ref: '#/components/schemas/PersonalInfo'
+ balance:
+ type: integer
+ title: Balance
+ exchange_balance:
+ type: integer
+ title: Exchange Balance
+ exchange_commitment:
+ type: integer
+ title: Exchange Commitment
+ pending_transfer:
+ type: integer
+ title: Pending Transfer
+ locked:
+ type: integer
+ title: Locked
+ modified:
+ anyOf:
+ - type: string
+ format: date-time
+ - type: 'null'
+ title: Modified
+ type: object
+ required:
+ - account_address
+ - personal_information
+ - balance
+ - exchange_balance
+ - exchange_commitment
+ - pending_transfer
+ - locked
+ - modified
+ title: HolderResponse
+ description: Holder schema (Response)
+ HoldersResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ holders:
+ items:
+ $ref: '#/components/schemas/HolderResponse'
+ type: array
+ title: Holders
+ type: object
+ required:
+ - result_set
+ - holders
+ title: HoldersResponse
+ description: Holders schema (Response)
+ IbetShareAdditionalIssue:
+ properties:
+ account_address:
+ type: string
+ title: Account Address
+ amount:
+ type: integer
+ maximum: 1000000000000.0
+ minimum: 1.0
+ title: Amount
+ type: object
+ required:
+ - account_address
+ - amount
+ title: IbetShareAdditionalIssue
+ description: ibet Share schema (Additional Issue)
+ IbetShareBulkTransferRequest:
+ properties:
+ transfer_list:
+ items:
+ $ref: '#/components/schemas/IbetShareTransfer'
+ type: array
+ maxItems: 500000
+ minItems: 1
+ title: Transfer List
+ description: List of data to be transferred
+ transaction_compression:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Transaction Compression
+ description: Transaction compression mode
+ type: object
+ required:
+ - transfer_list
+ title: IbetShareBulkTransferRequest
+ IbetShareContractVersion:
+ type: string
+ enum:
+ - '22_12'
+ - '24_06'
+ title: IbetShareContractVersion
+ IbetShareCreate:
+ properties:
+ name:
+ type: string
+ maxLength: 100
+ title: Name
+ issue_price:
+ type: integer
+ maximum: 5000000000.0
+ minimum: 0.0
+ title: Issue Price
+ principal_value:
+ type: integer
+ maximum: 5000000000.0
+ minimum: 0.0
+ title: Principal Value
+ total_supply:
+ type: integer
+ maximum: 1000000000000.0
+ minimum: 0.0
+ title: Total Supply
+ symbol:
+ anyOf:
+ - type: string
+ maxLength: 100
+ - type: 'null'
+ title: Symbol
+ dividends:
+ anyOf:
+ - type: number
+ maximum: 5000000000.0
+ minimum: 0.0
+ - type: 'null'
+ title: Dividends
+ dividend_record_date:
+ anyOf:
+ - type: string
+ pattern: ^(19[0-9]{2}|20[0-9]{2})(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])$
+ - type: string
+ enum:
+ - ''
+ const: ''
+ - type: 'null'
+ title: Dividend Record Date
+ dividend_payment_date:
+ anyOf:
+ - type: string
+ pattern: ^(19[0-9]{2}|20[0-9]{2})(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])$
+ - type: string
+ enum:
+ - ''
+ const: ''
+ - type: 'null'
+ title: Dividend Payment Date
+ cancellation_date:
+ anyOf:
+ - type: string
+ pattern: ^(19[0-9]{2}|20[0-9]{2})(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])$
+ - type: string
+ enum:
+ - ''
+ const: ''
+ - type: 'null'
+ title: Cancellation Date
+ transferable:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Transferable
+ status:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Status
+ is_offering:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Is Offering
+ tradable_exchange_contract_address:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Tradable Exchange Contract Address
+ personal_info_contract_address:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Personal Info Contract Address
+ require_personal_info_registered:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Require Personal Info Registered
+ contact_information:
+ anyOf:
+ - type: string
+ maxLength: 2000
+ - type: 'null'
+ title: Contact Information
+ privacy_policy:
+ anyOf:
+ - type: string
+ maxLength: 5000
+ - type: 'null'
+ title: Privacy Policy
+ transfer_approval_required:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Transfer Approval Required
+ is_canceled:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Is Canceled
+ type: object
+ required:
+ - name
+ - issue_price
+ - principal_value
+ - total_supply
+ title: IbetShareCreate
+ description: ibet Share schema (Create)
+ IbetShareRedeem:
+ properties:
+ account_address:
+ type: string
+ title: Account Address
+ amount:
+ type: integer
+ maximum: 1000000000000.0
+ minimum: 1.0
+ title: Amount
+ type: object
+ required:
+ - account_address
+ - amount
+ title: IbetShareRedeem
+ description: ibet Share schema (Redeem)
+ IbetShareResponse:
+ properties:
+ issuer_address:
+ type: string
+ title: Issuer Address
+ token_address:
+ type: string
+ title: Token Address
+ name:
+ type: string
+ title: Name
+ symbol:
+ type: string
+ title: Symbol
+ issue_price:
+ type: integer
+ title: Issue Price
+ principal_value:
+ type: integer
+ title: Principal Value
+ total_supply:
+ type: integer
+ title: Total Supply
+ dividends:
+ type: number
+ title: Dividends
+ dividend_record_date:
+ type: string
+ title: Dividend Record Date
+ dividend_payment_date:
+ type: string
+ title: Dividend Payment Date
+ cancellation_date:
+ type: string
+ title: Cancellation Date
+ transferable:
+ type: boolean
+ title: Transferable
+ transfer_approval_required:
+ type: boolean
+ title: Transfer Approval Required
+ status:
+ type: boolean
+ title: Status
+ is_offering:
+ type: boolean
+ title: Is Offering
+ tradable_exchange_contract_address:
+ type: string
+ title: Tradable Exchange Contract Address
+ personal_info_contract_address:
+ type: string
+ title: Personal Info Contract Address
+ require_personal_info_registered:
+ type: boolean
+ title: Require Personal Info Registered
+ contact_information:
+ type: string
+ title: Contact Information
+ privacy_policy:
+ type: string
+ title: Privacy Policy
+ issue_datetime:
+ type: string
+ title: Issue Datetime
+ token_status:
+ type: integer
+ title: Token Status
+ is_canceled:
+ type: boolean
+ title: Is Canceled
+ memo:
+ type: string
+ title: Memo
+ contract_version:
+ $ref: '#/components/schemas/IbetShareContractVersion'
+ type: object
+ required:
+ - issuer_address
+ - token_address
+ - name
+ - symbol
+ - issue_price
+ - principal_value
+ - total_supply
+ - dividends
+ - dividend_record_date
+ - dividend_payment_date
+ - cancellation_date
+ - transferable
+ - transfer_approval_required
+ - status
+ - is_offering
+ - tradable_exchange_contract_address
+ - personal_info_contract_address
+ - require_personal_info_registered
+ - contact_information
+ - privacy_policy
+ - issue_datetime
+ - token_status
+ - is_canceled
+ - memo
+ - contract_version
+ title: IbetShareResponse
+ description: ibet Share schema (Response)
+ IbetShareScheduledUpdate:
+ properties:
+ scheduled_datetime:
+ type: string
+ format: date-time
+ title: Scheduled Datetime
+ event_type:
+ $ref: '#/components/schemas/ScheduledEventType'
+ data:
+ $ref: '#/components/schemas/IbetShareUpdate'
+ type: object
+ required:
+ - scheduled_datetime
+ - event_type
+ - data
+ title: IbetShareScheduledUpdate
+ description: scheduled event (Request)
+ IbetShareTransfer:
+ properties:
+ token_address:
+ type: string
+ title: Token Address
+ from_address:
+ type: string
+ title: From Address
+ to_address:
+ type: string
+ title: To Address
+ amount:
+ type: integer
+ maximum: 1000000000000.0
+ minimum: 1.0
+ title: Amount
+ type: object
+ required:
+ - token_address
+ - from_address
+ - to_address
+ - amount
+ title: IbetShareTransfer
+ description: ibet Share schema (Transfer)
+ IbetShareUpdate:
+ properties:
+ cancellation_date:
+ anyOf:
+ - type: string
+ pattern: ^(19[0-9]{2}|20[0-9]{2})(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])$
+ - type: string
+ enum:
+ - ''
+ const: ''
+ - type: 'null'
+ title: Cancellation Date
+ dividend_record_date:
+ anyOf:
+ - type: string
+ pattern: ^(19[0-9]{2}|20[0-9]{2})(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])$
+ - type: string
+ enum:
+ - ''
+ const: ''
+ - type: 'null'
+ title: Dividend Record Date
+ dividend_payment_date:
+ anyOf:
+ - type: string
+ pattern: ^(19[0-9]{2}|20[0-9]{2})(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])$
+ - type: string
+ enum:
+ - ''
+ const: ''
+ - type: 'null'
+ title: Dividend Payment Date
+ dividends:
+ anyOf:
+ - type: number
+ maximum: 5000000000.0
+ minimum: 0.0
+ - type: 'null'
+ title: Dividends
+ tradable_exchange_contract_address:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Tradable Exchange Contract Address
+ personal_info_contract_address:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Personal Info Contract Address
+ require_personal_info_registered:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Require Personal Info Registered
+ transferable:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Transferable
+ status:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Status
+ is_offering:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Is Offering
+ contact_information:
+ anyOf:
+ - type: string
+ maxLength: 2000
+ - type: 'null'
+ title: Contact Information
+ privacy_policy:
+ anyOf:
+ - type: string
+ maxLength: 5000
+ - type: 'null'
+ title: Privacy Policy
+ transfer_approval_required:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Transfer Approval Required
+ principal_value:
+ anyOf:
+ - type: integer
+ maximum: 5000000000.0
+ minimum: 0.0
+ - type: 'null'
+ title: Principal Value
+ is_canceled:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Is Canceled
+ memo:
+ anyOf:
+ - type: string
+ maxLength: 10000
+ - type: 'null'
+ title: Memo
+ type: object
+ title: IbetShareUpdate
+ description: ibet Share schema (Update)
+ IbetStraightBondAdditionalIssue:
+ properties:
+ account_address:
+ type: string
+ title: Account Address
+ amount:
+ type: integer
+ maximum: 1000000000000.0
+ minimum: 1.0
+ title: Amount
+ type: object
+ required:
+ - account_address
+ - amount
+ title: IbetStraightBondAdditionalIssue
+ description: ibet Straight Bond schema (Additional Issue)
+ IbetStraightBondBulkTransferRequest:
+ properties:
+ transfer_list:
+ items:
+ $ref: '#/components/schemas/IbetStraightBondTransfer'
+ type: array
+ maxItems: 500000
+ minItems: 1
+ title: Transfer List
+ description: List of data to be transferred
+ transaction_compression:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Transaction Compression
+ description: Transaction compression mode
+ type: object
+ required:
+ - transfer_list
+ title: IbetStraightBondBulkTransferRequest
+ IbetStraightBondContractVersion:
+ type: string
+ enum:
+ - '22_12'
+ - '23_12'
+ - '24_06'
+ title: IbetStraightBondContractVersion
+ IbetStraightBondCreate:
+ properties:
+ name:
+ type: string
+ maxLength: 100
+ title: Name
+ total_supply:
+ type: integer
+ maximum: 1000000000000.0
+ minimum: 0.0
+ title: Total Supply
+ face_value:
+ type: integer
+ maximum: 5000000000.0
+ minimum: 0.0
+ title: Face Value
+ face_value_currency:
+ type: string
+ maxLength: 3
+ minLength: 3
+ title: Face Value Currency
+ purpose:
+ type: string
+ maxLength: 2000
+ title: Purpose
+ symbol:
+ anyOf:
+ - type: string
+ maxLength: 100
+ - type: 'null'
+ title: Symbol
+ redemption_date:
+ anyOf:
+ - type: string
+ pattern: ^(19[0-9]{2}|20[0-9]{2})(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])$
+ - type: 'null'
+ title: Redemption Date
+ redemption_value:
+ anyOf:
+ - type: integer
+ maximum: 5000000000.0
+ minimum: 0.0
+ - type: 'null'
+ title: Redemption Value
+ redemption_value_currency:
+ anyOf:
+ - type: string
+ maxLength: 3
+ minLength: 3
+ - type: 'null'
+ title: Redemption Value Currency
+ return_date:
+ anyOf:
+ - type: string
+ pattern: ^(19[0-9]{2}|20[0-9]{2})(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])$
+ - type: 'null'
+ title: Return Date
+ return_amount:
+ anyOf:
+ - type: string
+ maxLength: 2000
+ - type: 'null'
+ title: Return Amount
+ interest_rate:
+ anyOf:
+ - type: number
+ maximum: 100.0
+ minimum: 0.0
+ - type: 'null'
+ title: Interest Rate
+ interest_payment_date:
+ anyOf:
+ - items:
+ type: string
+ pattern: ^(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])$
+ type: array
+ - type: 'null'
+ title: Interest Payment Date
+ interest_payment_currency:
+ anyOf:
+ - type: string
+ maxLength: 3
+ minLength: 3
+ - type: 'null'
+ title: Interest Payment Currency
+ base_fx_rate:
+ anyOf:
+ - type: number
+ minimum: 0.0
+ - type: 'null'
+ title: Base Fx Rate
+ transferable:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Transferable
+ is_redeemed:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Is Redeemed
+ status:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Status
+ is_offering:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Is Offering
+ tradable_exchange_contract_address:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Tradable Exchange Contract Address
+ personal_info_contract_address:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Personal Info Contract Address
+ require_personal_info_registered:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Require Personal Info Registered
+ image_url:
+ anyOf:
+ - items:
+ type: string
+ type: array
+ - type: 'null'
+ title: Image Url
+ contact_information:
+ anyOf:
+ - type: string
+ maxLength: 2000
+ - type: 'null'
+ title: Contact Information
+ privacy_policy:
+ anyOf:
+ - type: string
+ maxLength: 5000
+ - type: 'null'
+ title: Privacy Policy
+ transfer_approval_required:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Transfer Approval Required
+ type: object
+ required:
+ - name
+ - total_supply
+ - face_value
+ - face_value_currency
+ - purpose
+ title: IbetStraightBondCreate
+ description: ibet Straight Bond schema (Create)
+ IbetStraightBondRedeem:
+ properties:
+ account_address:
+ type: string
+ title: Account Address
+ amount:
+ type: integer
+ maximum: 1000000000000.0
+ minimum: 1.0
+ title: Amount
+ type: object
+ required:
+ - account_address
+ - amount
+ title: IbetStraightBondRedeem
+ description: ibet Straight Bond schema (Redeem)
+ IbetStraightBondResponse:
+ properties:
+ issuer_address:
+ type: string
+ title: Issuer Address
+ token_address:
+ type: string
+ title: Token Address
+ name:
+ type: string
+ title: Name
+ symbol:
+ type: string
+ title: Symbol
+ total_supply:
+ type: integer
+ title: Total Supply
+ face_value:
+ type: integer
+ title: Face Value
+ face_value_currency:
+ type: string
+ title: Face Value Currency
+ redemption_date:
+ type: string
+ title: Redemption Date
+ redemption_value:
+ type: integer
+ title: Redemption Value
+ redemption_value_currency:
+ type: string
+ title: Redemption Value Currency
+ return_date:
+ type: string
+ title: Return Date
+ return_amount:
+ type: string
+ title: Return Amount
+ purpose:
+ type: string
+ title: Purpose
+ interest_rate:
+ type: number
+ title: Interest Rate
+ interest_payment_date:
+ items:
+ type: string
+ type: array
+ title: Interest Payment Date
+ interest_payment_currency:
+ type: string
+ title: Interest Payment Currency
+ base_fx_rate:
+ type: number
+ title: Base Fx Rate
+ transferable:
+ type: boolean
+ title: Transferable
+ is_redeemed:
+ type: boolean
+ title: Is Redeemed
+ status:
+ type: boolean
+ title: Status
+ is_offering:
+ type: boolean
+ title: Is Offering
+ tradable_exchange_contract_address:
+ type: string
+ title: Tradable Exchange Contract Address
+ personal_info_contract_address:
+ type: string
+ title: Personal Info Contract Address
+ require_personal_info_registered:
+ type: boolean
+ title: Require Personal Info Registered
+ contact_information:
+ type: string
+ title: Contact Information
+ privacy_policy:
+ type: string
+ title: Privacy Policy
+ issue_datetime:
+ type: string
+ title: Issue Datetime
+ token_status:
+ type: integer
+ title: Token Status
+ transfer_approval_required:
+ type: boolean
+ title: Transfer Approval Required
+ memo:
+ type: string
+ title: Memo
+ contract_version:
+ $ref: '#/components/schemas/IbetStraightBondContractVersion'
+ type: object
+ required:
+ - issuer_address
+ - token_address
+ - name
+ - symbol
+ - total_supply
+ - face_value
+ - face_value_currency
+ - redemption_date
+ - redemption_value
+ - redemption_value_currency
+ - return_date
+ - return_amount
+ - purpose
+ - interest_rate
+ - interest_payment_date
+ - interest_payment_currency
+ - base_fx_rate
+ - transferable
+ - is_redeemed
+ - status
+ - is_offering
+ - tradable_exchange_contract_address
+ - personal_info_contract_address
+ - require_personal_info_registered
+ - contact_information
+ - privacy_policy
+ - issue_datetime
+ - token_status
+ - transfer_approval_required
+ - memo
+ - contract_version
+ title: IbetStraightBondResponse
+ description: ibet Straight Bond schema (Response)
+ IbetStraightBondScheduledUpdate:
+ properties:
+ scheduled_datetime:
+ type: string
+ format: date-time
+ title: Scheduled Datetime
+ event_type:
+ $ref: '#/components/schemas/ScheduledEventType'
+ data:
+ $ref: '#/components/schemas/IbetStraightBondUpdate'
+ type: object
+ required:
+ - scheduled_datetime
+ - event_type
+ - data
+ title: IbetStraightBondScheduledUpdate
+ description: scheduled event (Request)
+ IbetStraightBondTransfer:
+ properties:
+ token_address:
+ type: string
+ title: Token Address
+ from_address:
+ type: string
+ title: From Address
+ to_address:
+ type: string
+ title: To Address
+ amount:
+ type: integer
+ maximum: 1000000000000.0
+ minimum: 1.0
+ title: Amount
+ type: object
+ required:
+ - token_address
+ - from_address
+ - to_address
+ - amount
+ title: IbetStraightBondTransfer
+ description: ibet Straight Bond schema (Transfer)
+ IbetStraightBondUpdate:
+ properties:
+ face_value:
+ anyOf:
+ - type: integer
+ maximum: 5000000000.0
+ minimum: 0.0
+ - type: 'null'
+ title: Face Value
+ face_value_currency:
+ anyOf:
+ - type: string
+ maxLength: 3
+ minLength: 3
+ - type: 'null'
+ title: Face Value Currency
+ interest_rate:
+ anyOf:
+ - type: number
+ maximum: 100.0
+ minimum: 0.0
+ - type: 'null'
+ title: Interest Rate
+ interest_payment_date:
+ anyOf:
+ - items:
+ type: string
+ pattern: ^(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])$
+ type: array
+ - type: 'null'
+ title: Interest Payment Date
+ interest_payment_currency:
+ anyOf:
+ - type: string
+ maxLength: 3
+ minLength: 3
+ - type: string
+ enum:
+ - ''
+ const: ''
+ - type: 'null'
+ title: Interest Payment Currency
+ redemption_value:
+ anyOf:
+ - type: integer
+ maximum: 5000000000.0
+ minimum: 0.0
+ - type: 'null'
+ title: Redemption Value
+ redemption_value_currency:
+ anyOf:
+ - type: string
+ maxLength: 3
+ minLength: 3
+ - type: string
+ enum:
+ - ''
+ const: ''
+ - type: 'null'
+ title: Redemption Value Currency
+ base_fx_rate:
+ anyOf:
+ - type: number
+ minimum: 0.0
+ - type: 'null'
+ title: Base Fx Rate
+ transferable:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Transferable
+ status:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Status
+ is_offering:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Is Offering
+ is_redeemed:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Is Redeemed
+ tradable_exchange_contract_address:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Tradable Exchange Contract Address
+ personal_info_contract_address:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Personal Info Contract Address
+ require_personal_info_registered:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Require Personal Info Registered
+ contact_information:
+ anyOf:
+ - type: string
+ maxLength: 2000
+ - type: 'null'
+ title: Contact Information
+ privacy_policy:
+ anyOf:
+ - type: string
+ maxLength: 5000
+ - type: 'null'
+ title: Privacy Policy
+ transfer_approval_required:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Transfer Approval Required
+ memo:
+ anyOf:
+ - type: string
+ maxLength: 10000
+ - type: 'null'
+ title: Memo
+ type: object
+ title: IbetStraightBondUpdate
+ description: ibet Straight Bond schema (Update)
+ Integer64bitLimitExceededErrorCode:
+ type: integer
+ enum:
+ - 5
+ const: 5
+ title: Integer64bitLimitExceededErrorCode
+ Integer64bitLimitExceededErrorMetainfo:
+ properties:
+ code:
+ allOf:
+ - $ref: '#/components/schemas/Integer64bitLimitExceededErrorCode'
+ examples:
+ - 5
+ title:
+ type: string
+ title: Title
+ examples:
+ - Integer64bitLimitExceededError
+ type: object
+ required:
+ - code
+ - title
+ title: Integer64bitLimitExceededErrorMetainfo
+ Integer64bitLimitExceededErrorResponse:
+ properties:
+ meta:
+ $ref: '#/components/schemas/Integer64bitLimitExceededErrorMetainfo'
+ detail:
+ type: string
+ title: Detail
+ type: object
+ required:
+ - meta
+ - detail
+ title: Integer64bitLimitExceededErrorResponse
+ InvalidParameterErrorCode:
+ type: integer
+ enum:
+ - 1
+ const: 1
+ title: InvalidParameterErrorCode
+ InvalidParameterErrorMetainfo:
+ properties:
+ code:
+ allOf:
+ - $ref: '#/components/schemas/InvalidParameterErrorCode'
+ examples:
+ - 1
+ title:
+ type: string
+ title: Title
+ examples:
+ - InvalidParameterError
+ type: object
+ required:
+ - code
+ - title
+ title: InvalidParameterErrorMetainfo
+ InvalidParameterErrorResponse:
+ properties:
+ meta:
+ $ref: '#/components/schemas/InvalidParameterErrorMetainfo'
+ detail:
+ type: string
+ title: Detail
+ type: object
+ required:
+ - meta
+ - detail
+ title: InvalidParameterErrorResponse
+ IssueErrorMetaInfo:
+ properties:
+ token_address:
+ type: string
+ title: Token Address
+ token_type:
+ $ref: '#/components/schemas/TokenType'
+ arguments:
+ type: object
+ title: Arguments
+ type: object
+ required:
+ - token_address
+ - token_type
+ - arguments
+ title: IssueErrorMetaInfo
+ IssueErrorNotification:
+ properties:
+ notice_id:
+ type: string
+ title: Notice Id
+ issuer_address:
+ type: string
+ title: Issuer Address
+ priority:
+ type: integer
+ title: Priority
+ notice_code:
+ type: integer
+ maximum: 2.0
+ minimum: 0.0
+ title: Notice Code
+ description: |2
+ - 0: Issuer does not exist
+ - 1: Could not get the private key of the issuer
+ - 2: Failed to send transaction
+ created:
+ type: string
+ title: Created
+ notice_type:
+ type: string
+ enum:
+ - IssueError
+ const: IssueError
+ title: Notice Type
+ metainfo:
+ $ref: '#/components/schemas/IssueErrorMetaInfo'
+ type: object
+ required:
+ - notice_id
+ - issuer_address
+ - priority
+ - notice_code
+ - created
+ - notice_type
+ - metainfo
+ title: IssueErrorNotification
+ IssueRedeemEvent:
+ properties:
+ transaction_hash:
+ type: string
+ title: Transaction Hash
+ token_address:
+ type: string
+ title: Token Address
+ locked_address:
+ type: string
+ title: Locked Address
+ target_address:
+ type: string
+ title: Target Address
+ amount:
+ type: integer
+ title: Amount
+ block_timestamp:
+ type: string
+ title: Block Timestamp
+ type: object
+ required:
+ - transaction_hash
+ - token_address
+ - locked_address
+ - target_address
+ - amount
+ - block_timestamp
+ title: IssueRedeemEvent
+ description: Issue/Redeem event
+ IssueRedeemHistoryResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ history:
+ items:
+ $ref: '#/components/schemas/IssueRedeemEvent'
+ type: array
+ title: History
+ type: object
+ required:
+ - result_set
+ - history
+ title: IssueRedeemHistoryResponse
+ description: Issue/Redeem history
+ IssueRedeemSortItem:
+ type: string
+ enum:
+ - block_timestamp
+ - locked_address
+ - target_address
+ - amount
+ title: IssueRedeemSortItem
+ description: Issue/Redeem sort item
+ LedgerDetailsDataListAllResponse:
+ properties:
+ data_id:
+ type: string
+ title: Data Id
+ count:
+ type: integer
+ title: Count
+ created:
+ type: string
+ format: date-time
+ title: Created
+ type: object
+ required:
+ - data_id
+ - count
+ - created
+ title: LedgerDetailsDataListAllResponse
+ description: Ledger Details Data(List All) schema (Response)
+ LedgerDetailsDataResponse:
+ properties:
+ data_id:
+ type: string
+ title: Data Id
+ type: object
+ required:
+ - data_id
+ title: LedgerDetailsDataResponse
+ description: Ledger Details Data schema (Response)
+ LedgerDetailsDataTemplateResponse:
+ properties:
+ type:
+ $ref: '#/components/schemas/LedgerDetailsDataType'
+ source:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Source
+ type: object
+ required:
+ - type
+ - source
+ title: LedgerDetailsDataTemplateResponse
+ description: Ledger Details Data Template schema (Response)
+ LedgerDetailsDataType:
+ type: string
+ enum:
+ - ibetfin
+ - db
+ title: LedgerDetailsDataType
+ LedgerDetailsTemplateResponse:
+ properties:
+ token_detail_type:
+ type: string
+ title: Token Detail Type
+ headers:
+ anyOf:
+ - items:
+ type: object
+ type: array
+ - type: 'null'
+ title: Headers
+ data:
+ $ref: '#/components/schemas/LedgerDetailsDataTemplateResponse'
+ footers:
+ anyOf:
+ - items:
+ type: object
+ type: array
+ - type: 'null'
+ title: Footers
+ type: object
+ required:
+ - token_detail_type
+ - headers
+ - data
+ - footers
+ title: LedgerDetailsTemplateResponse
+ description: Ledger Details Template schema (Response)
+ LedgerResponse:
+ properties:
+ id:
+ type: integer
+ title: Id
+ token_address:
+ type: string
+ title: Token Address
+ token_type:
+ $ref: '#/components/schemas/TokenType'
+ created:
+ type: string
+ format: date-time
+ title: Created
+ type: object
+ required:
+ - id
+ - token_address
+ - token_type
+ - created
+ title: LedgerResponse
+ description: Ledger schema (Response)
+ LedgerTemplateResponse:
+ properties:
+ token_name:
+ type: string
+ title: Token Name
+ headers:
+ anyOf:
+ - items:
+ type: object
+ type: array
+ - type: 'null'
+ title: Headers
+ details:
+ items:
+ $ref: '#/components/schemas/LedgerDetailsTemplateResponse'
+ type: array
+ title: Details
+ footers:
+ anyOf:
+ - items:
+ type: object
+ type: array
+ - type: 'null'
+ title: Footers
+ type: object
+ required:
+ - token_name
+ - headers
+ - details
+ - footers
+ title: LedgerTemplateResponse
+ description: Ledger Template schema (Response)
+ ListAllDVPAgentAccountResponse:
+ items:
+ $ref: '#/components/schemas/DVPAgentAccountResponse'
+ type: array
+ title: ListAllDVPAgentAccountResponse
+ description: DVP agent account list reference schema (RESPONSE)
+ ListAllDVPDeliveriesResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ deliveries:
+ items:
+ $ref: '#/components/schemas/RetrieveDVPDeliveryResponse'
+ type: array
+ title: Deliveries
+ type: object
+ required:
+ - result_set
+ - deliveries
+ title: ListAllDVPDeliveriesResponse
+ description: List all DVP delivery schema (Response)
+ ListAllE2EMessagingResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ e2e_messages:
+ items:
+ $ref: '#/components/schemas/E2EMessagingResponse'
+ type: array
+ title: E2E Messages
+ type: object
+ required:
+ - result_set
+ - e2e_messages
+ title: ListAllE2EMessagingResponse
+ description: List All E2E Messaging schema (Response)
+ ListAllFilesResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ files:
+ items:
+ $ref: '#/components/schemas/FileResponse'
+ type: array
+ title: Files
+ type: object
+ required:
+ - result_set
+ - files
+ title: ListAllFilesResponse
+ description: List All Files schema (Response)
+ ListAllFreezeLogAccountResponse:
+ items:
+ $ref: '#/components/schemas/FreezeLogAccountResponse'
+ type: array
+ title: ListAllFreezeLogAccountResponse
+ description: Freeze-logging account list reference schema (RESPONSE)
+ ListAllHoldersSortItem:
+ type: string
+ enum:
+ - created
+ - account_address
+ - balance
+ - pending_transfer
+ - locked
+ - balance_and_pending_transfer
+ - key_manager
+ - holder_name
+ title: ListAllHoldersSortItem
+ ListAllLedgerDetailsDataResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ details_data:
+ items:
+ $ref: '#/components/schemas/LedgerDetailsDataListAllResponse'
+ type: array
+ title: Details Data
+ type: object
+ required:
+ - result_set
+ - details_data
+ title: ListAllLedgerDetailsDataResponse
+ description: List All Ledger Details Data schema (Response)
+ ListAllLedgerHistoryResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ ledgers:
+ items:
+ $ref: '#/components/schemas/LedgerResponse'
+ type: array
+ title: Ledgers
+ type: object
+ required:
+ - result_set
+ - ledgers
+ title: ListAllLedgerHistoryResponse
+ description: List All Ledger History schema (Response)
+ ListAllLockEventsResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ events:
+ items:
+ $ref: '#/components/schemas/LockEvent'
+ type: array
+ title: Events
+ description: Lock/Unlock event list
+ type: object
+ required:
+ - result_set
+ - events
+ title: ListAllLockEventsResponse
+ description: List All Lock/Unlock events (Response)
+ ListAllLockEventsSortItem:
+ type: string
+ enum:
+ - token_address
+ - lock_address
+ - recipient_address
+ - value
+ - block_timestamp
+ title: ListAllLockEventsSortItem
+ ListAllLockedPositionResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ locked_positions:
+ items:
+ $ref: '#/components/schemas/LockedPosition'
+ type: array
+ title: Locked Positions
+ description: Locked position list
+ type: object
+ required:
+ - result_set
+ - locked_positions
+ title: ListAllLockedPositionResponse
+ description: List All Locked Position schema (Response)
+ ListAllNotificationsResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ notifications:
+ items:
+ $ref: '#/components/schemas/NotificationsListResponse'
+ type: array
+ title: Notifications
+ type: object
+ required:
+ - result_set
+ - notifications
+ title: ListAllNotificationsResponse
+ description: List All Notifications schema (Response)
+ ListAllPositionResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ positions:
+ items:
+ $ref: '#/components/schemas/Position'
+ type: array
+ title: Positions
+ description: Position list
+ type: object
+ required:
+ - result_set
+ - positions
+ title: ListAllPositionResponse
+ description: List All Position schema (Response)
+ ListAllTokenHolderCollectionsResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ collections:
+ items:
+ $ref: '#/components/schemas/RetrieveTokenHolderCollectionResponse'
+ type: array
+ title: Collections
+ type: object
+ required:
+ - result_set
+ - collections
+ title: ListAllTokenHolderCollectionsResponse
+ description: List All Token Holders Collections schema (RESPONSE)
+ ListAllTokenLockEventsResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ events:
+ items:
+ $ref: '#/components/schemas/LockEvent'
+ type: array
+ title: Events
+ description: Lock/Unlock event list
+ type: object
+ required:
+ - result_set
+ - events
+ title: ListAllTokenLockEventsResponse
+ description: List All Lock/Unlock events (Response)
+ ListAllTokenLockEventsSortItem:
+ type: string
+ enum:
+ - account_address
+ - lock_address
+ - recipient_address
+ - value
+ - block_timestamp
+ title: ListAllTokenLockEventsSortItem
+ ListBatchIssueRedeemUploadResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ uploads:
+ items:
+ $ref: '#/components/schemas/BatchIssueRedeemUpload'
+ type: array
+ title: Uploads
+ type: object
+ required:
+ - result_set
+ - uploads
+ title: ListBatchIssueRedeemUploadResponse
+ description: List All Batch issue/redeem Upload(RESPONSE)
+ ListBatchRegisterPersonalInfoUploadResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ uploads:
+ items:
+ $ref: '#/components/schemas/BatchRegisterPersonalInfoUploadResponse'
+ type: array
+ title: Uploads
+ type: object
+ required:
+ - result_set
+ - uploads
+ title: ListBatchRegisterPersonalInfoUploadResponse
+ description: List All Batch Register PersonalInfo Upload (Response)
+ ListTokenHistorySortItem:
+ type: string
+ enum:
+ - created
+ - operation_category
+ title: ListTokenHistorySortItem
+ description: Sort item of token history
+ ListTokenHoldersPersonalInfoHistoryResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ personal_info:
+ items:
+ $ref: '#/components/schemas/PersonalInfoHistory'
+ type: array
+ title: Personal Info
+ type: object
+ required:
+ - result_set
+ - personal_info
+ title: ListTokenHoldersPersonalInfoHistoryResponse
+ description: List All Token Holders PersonalInfo Histories (Response)
+ ListTokenHoldersPersonalInfoResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ personal_info:
+ items:
+ $ref: '#/components/schemas/PersonalInfoIndex'
+ type: array
+ title: Personal Info
+ type: object
+ required:
+ - result_set
+ - personal_info
+ title: ListTokenHoldersPersonalInfoResponse
+ description: List All Token Holders PersonalInfo (Response)
+ ListTokenHoldersPersonalInfoSortItem:
+ type: string
+ enum:
+ - account_address
+ - created
+ - modified
+ title: ListTokenHoldersPersonalInfoSortItem
+ ListTokenOperationLogHistoryResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ history:
+ items:
+ $ref: '#/components/schemas/TokenOperationLogResponse'
+ type: array
+ title: History
+ description: token update histories
+ default: []
+ type: object
+ required:
+ - result_set
+ title: ListTokenOperationLogHistoryResponse
+ ListTransferApprovalHistorySortItem:
+ type: string
+ enum:
+ - id
+ - exchange_address
+ - application_id
+ - from_address
+ - to_address
+ - amount
+ - application_datetime
+ - approval_datetime
+ - status
+ title: ListTransferApprovalHistorySortItem
+ ListTransferHistorySortItem:
+ type: string
+ enum:
+ - block_timestamp
+ - from_address
+ - to_address
+ - from_address_name
+ - to_address_name
+ - amount
+ title: ListTransferHistorySortItem
+ LockEvent:
+ properties:
+ category:
+ allOf:
+ - $ref: '#/components/schemas/LockEventCategory'
+ description: Event category
+ transaction_hash:
+ type: string
+ title: Transaction Hash
+ description: Transaction hash
+ msg_sender:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Msg Sender
+ description: Message sender
+ issuer_address:
+ type: string
+ title: Issuer Address
+ description: Issuer address
+ token_address:
+ type: string
+ title: Token Address
+ description: Token address
+ token_type:
+ allOf:
+ - $ref: '#/components/schemas/TokenType'
+ description: Token type
+ token_name:
+ type: string
+ title: Token Name
+ description: Token name
+ lock_address:
+ type: string
+ title: Lock Address
+ description: Lock address
+ account_address:
+ type: string
+ title: Account Address
+ description: Account address
+ recipient_address:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Recipient Address
+ description: Recipient address
+ value:
+ type: integer
+ title: Value
+ description: Lock/Unlock amount
+ data:
+ type: object
+ title: Data
+ description: Message at lock/unlock
+ block_timestamp:
+ type: string
+ title: Block Timestamp
+ description: block_timestamp when Lock log was emitted
+ type: object
+ required:
+ - category
+ - transaction_hash
+ - issuer_address
+ - token_address
+ - token_type
+ - token_name
+ - lock_address
+ - account_address
+ - value
+ - data
+ - block_timestamp
+ title: LockEvent
+ LockEventCategory:
+ type: string
+ enum:
+ - Lock
+ - Unlock
+ title: LockEventCategory
+ LockInfoMetaInfo:
+ properties:
+ token_address:
+ type: string
+ title: Token Address
+ token_type:
+ $ref: '#/components/schemas/TokenType'
+ lock_address:
+ type: string
+ title: Lock Address
+ account_address:
+ type: string
+ title: Account Address
+ value:
+ type: integer
+ title: Value
+ data:
+ type: object
+ title: Data
+ type: object
+ required:
+ - token_address
+ - token_type
+ - lock_address
+ - account_address
+ - value
+ - data
+ title: LockInfoMetaInfo
+ LockInfoNotification:
+ properties:
+ notice_id:
+ type: string
+ title: Notice Id
+ issuer_address:
+ type: string
+ title: Issuer Address
+ priority:
+ type: integer
+ title: Priority
+ notice_code:
+ type: integer
+ maximum: 0.0
+ minimum: 0.0
+ title: Notice Code
+ description: " - 0: Balance is locked\n"
+ created:
+ type: string
+ title: Created
+ notice_type:
+ type: string
+ enum:
+ - LockInfo
+ const: LockInfo
+ title: Notice Type
+ metainfo:
+ $ref: '#/components/schemas/LockInfoMetaInfo'
+ type: object
+ required:
+ - notice_id
+ - issuer_address
+ - priority
+ - notice_code
+ - created
+ - notice_type
+ - metainfo
+ title: LockInfoNotification
+ LockedPosition:
+ properties:
+ issuer_address:
+ type: string
+ title: Issuer Address
+ description: Issuer address
+ token_address:
+ type: string
+ title: Token Address
+ description: Token address
+ token_type:
+ allOf:
+ - $ref: '#/components/schemas/TokenType'
+ description: Token type
+ token_name:
+ type: string
+ title: Token Name
+ description: Token name
+ lock_address:
+ type: string
+ title: Lock Address
+ description: Lock address
+ locked:
+ type: integer
+ title: Locked
+ description: Locked amount
+ type: object
+ required:
+ - issuer_address
+ - token_address
+ - token_type
+ - token_name
+ - lock_address
+ - locked
+ title: LockedPosition
+ description: Locked Position
+ NotificationsListResponse:
+ anyOf:
+ - $ref: '#/components/schemas/IssueErrorNotification'
+ - $ref: '#/components/schemas/BulkTransferErrorNotification'
+ - $ref: '#/components/schemas/ScheduleEventErrorNotification'
+ - $ref: '#/components/schemas/TransferApprovalInfoNotification'
+ - $ref: '#/components/schemas/CreateLedgerInfoNotification'
+ - $ref: '#/components/schemas/BatchRegisterPersonalInfoErrorNotification'
+ - $ref: '#/components/schemas/BatchIssueRedeemProcessedNotification'
+ - $ref: '#/components/schemas/LockInfoNotification'
+ - $ref: '#/components/schemas/UnlockInfoNotification'
+ title: NotificationsListResponse
+ description: Notifications List schema (Response)
+ OperationNotAllowedStateErrorCode:
+ type: integer
+ enum:
+ - 101
+ const: 101
+ title: OperationNotAllowedStateErrorCode
+ OperationNotAllowedStateErrorMetainfo:
+ properties:
+ code:
+ allOf:
+ - $ref: '#/components/schemas/OperationNotAllowedStateErrorCode'
+ examples:
+ - 0
+ title:
+ type: string
+ title: Title
+ examples:
+ - OperationNotAllowedStateError
+ type: object
+ required:
+ - code
+ - title
+ title: OperationNotAllowedStateErrorMetainfo
+ OperationNotAllowedStateErrorResponse:
+ properties:
+ meta:
+ $ref: '#/components/schemas/OperationNotAllowedStateErrorMetainfo'
+ detail:
+ type: string
+ title: Detail
+ type: object
+ required:
+ - meta
+ - detail
+ title: OperationNotAllowedStateErrorResponse
+ description: Error returned when server-side data is not ready to process the
+ request
+ OperationNotSupportedVersionErrorCode:
+ type: integer
+ enum:
+ - 6
+ const: 6
+ title: OperationNotSupportedVersionErrorCode
+ OperationNotSupportedVersionErrorMetainfo:
+ properties:
+ code:
+ allOf:
+ - $ref: '#/components/schemas/OperationNotSupportedVersionErrorCode'
+ examples:
+ - 6
+ title:
+ type: string
+ title: Title
+ examples:
+ - OperationNotSupportedVersionError
+ type: object
+ required:
+ - code
+ - title
+ title: OperationNotSupportedVersionErrorMetainfo
+ OperationNotSupportedVersionErrorResponse:
+ properties:
+ meta:
+ $ref: '#/components/schemas/OperationNotSupportedVersionErrorMetainfo'
+ detail:
+ type: string
+ title: Detail
+ type: object
+ required:
+ - meta
+ - detail
+ title: OperationNotSupportedVersionErrorResponse
+ description: The token version for which the operation is not supported
+ PersonalInfo:
+ properties:
+ key_manager:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Key Manager
+ name:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Name
+ postal_code:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Postal Code
+ address:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Address
+ email:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Email
+ birth:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Birth
+ is_corporate:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Is Corporate
+ tax_category:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Tax Category
+ type: object
+ required:
+ - key_manager
+ - name
+ - postal_code
+ - address
+ - email
+ - birth
+ - is_corporate
+ - tax_category
+ title: PersonalInfo
+ PersonalInfoEventType:
+ type: string
+ enum:
+ - register
+ - modify
+ title: PersonalInfoEventType
+ PersonalInfoHistory:
+ properties:
+ id:
+ type: integer
+ title: Id
+ account_address:
+ type: string
+ title: Account Address
+ event_type:
+ $ref: '#/components/schemas/PersonalInfoEventType'
+ personal_info:
+ $ref: '#/components/schemas/PersonalInfo'
+ block_timestamp:
+ type: string
+ format: date-time
+ title: Block Timestamp
+ created:
+ type: string
+ format: date-time
+ title: Created
+ type: object
+ required:
+ - id
+ - account_address
+ - event_type
+ - personal_info
+ - block_timestamp
+ - created
+ title: PersonalInfoHistory
+ description: Personal Information History schema
+ PersonalInfoIndex:
+ properties:
+ id:
+ type: integer
+ title: Id
+ account_address:
+ type: string
+ title: Account Address
+ personal_info:
+ $ref: '#/components/schemas/PersonalInfo'
+ created:
+ type: string
+ format: date-time
+ title: Created
+ modified:
+ type: string
+ format: date-time
+ title: Modified
+ type: object
+ required:
+ - id
+ - account_address
+ - personal_info
+ - created
+ - modified
+ title: PersonalInfoIndex
+ description: Personal Information Index schema
+ Position:
+ properties:
+ issuer_address:
+ type: string
+ title: Issuer Address
+ description: Issuer address
+ token_address:
+ type: string
+ title: Token Address
+ description: Token address
+ token_type:
+ allOf:
+ - $ref: '#/components/schemas/TokenType'
+ description: Token type
+ token_name:
+ type: string
+ title: Token Name
+ description: Token name
+ balance:
+ type: integer
+ title: Balance
+ description: Balance
+ exchange_balance:
+ type: integer
+ title: Exchange Balance
+ description: Balance on the exchange contract
+ exchange_commitment:
+ type: integer
+ title: Exchange Commitment
+ description: Commitment on the exchange contract
+ pending_transfer:
+ type: integer
+ title: Pending Transfer
+ description: Pending transfer amount
+ locked:
+ type: integer
+ title: Locked
+ description: Total locked amount
+ type: object
+ required:
+ - issuer_address
+ - token_address
+ - token_type
+ - token_name
+ - balance
+ - exchange_balance
+ - exchange_commitment
+ - pending_transfer
+ - locked
+ title: Position
+ description: Position
+ PositionResponse:
+ allOf:
+ - $ref: '#/components/schemas/Position'
+ title: PositionResponse
+ description: Position schema (Response)
+ RecordNewFreezeLogRequest:
+ properties:
+ account_address:
+ type: string
+ title: Account Address
+ description: Logging account address
+ eoa_password:
+ type: string
+ title: Eoa Password
+ description: Logging account key file password
+ log_message:
+ type: string
+ title: Log Message
+ description: Log message
+ freezing_grace_block_count:
+ type: integer
+ exclusiveMinimum: 0.0
+ title: Freezing Grace Block Count
+ description: Freezing grace block count
+ type: object
+ required:
+ - account_address
+ - eoa_password
+ - log_message
+ - freezing_grace_block_count
+ title: RecordNewFreezeLogRequest
+ description: Record new freeze log schema (REQUEST)
+ RecordNewFreezeLogResponse:
+ properties:
+ log_index:
+ type: integer
+ title: Log Index
+ type: object
+ required:
+ - log_index
+ title: RecordNewFreezeLogResponse
+ description: New freeze-log recording schema (RESPONSE)
+ RegisterPersonalInfoRequest:
+ properties:
+ name:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Name
+ postal_code:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Postal Code
+ address:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Address
+ email:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Email
+ birth:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Birth
+ is_corporate:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Is Corporate
+ tax_category:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Tax Category
+ account_address:
+ type: string
+ title: Account Address
+ key_manager:
+ type: string
+ title: Key Manager
+ type: object
+ required:
+ - account_address
+ - key_manager
+ title: RegisterPersonalInfoRequest
+ description: Register Personal Information schema (REQUEST)
+ ResponseLimitExceededErrorCode:
+ type: integer
+ enum:
+ - 4
+ const: 4
+ title: ResponseLimitExceededErrorCode
+ ResponseLimitExceededErrorMetainfo:
+ properties:
+ code:
+ allOf:
+ - $ref: '#/components/schemas/ResponseLimitExceededErrorCode'
+ examples:
+ - 4
+ title:
+ type: string
+ title: Title
+ examples:
+ - ResponseLimitExceededError
+ type: object
+ required:
+ - code
+ - title
+ title: ResponseLimitExceededErrorMetainfo
+ ResponseLimitExceededErrorResponse:
+ properties:
+ meta:
+ $ref: '#/components/schemas/ResponseLimitExceededErrorMetainfo'
+ detail:
+ type: string
+ title: Detail
+ type: object
+ required:
+ - meta
+ - detail
+ title: ResponseLimitExceededErrorResponse
+ ResultSet:
+ properties:
+ count:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Count
+ offset:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Offset
+ limit:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Limit
+ total:
+ anyOf:
+ - type: integer
+ - type: 'null'
+ title: Total
+ type: object
+ required:
+ - count
+ - offset
+ - limit
+ - total
+ title: ResultSet
+ description: result set for pagination
+ RetrieveDVPDeliveryResponse:
+ properties:
+ exchange_address:
+ type: string
+ title: Exchange Address
+ delivery_id:
+ type: integer
+ title: Delivery Id
+ token_address:
+ type: string
+ title: Token Address
+ buyer_address:
+ type: string
+ title: Buyer Address
+ seller_address:
+ type: string
+ title: Seller Address
+ amount:
+ type: integer
+ title: Amount
+ agent_address:
+ type: string
+ title: Agent Address
+ data:
+ type: string
+ title: Data
+ examples:
+ - '{}'
+ - '{"type": "primary"}'
+ create_blocktimestamp:
+ type: string
+ title: Create Blocktimestamp
+ create_transaction_hash:
+ type: string
+ title: Create Transaction Hash
+ cancel_blocktimestamp:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Cancel Blocktimestamp
+ cancel_transaction_hash:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Cancel Transaction Hash
+ confirm_blocktimestamp:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Confirm Blocktimestamp
+ confirm_transaction_hash:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Confirm Transaction Hash
+ finish_blocktimestamp:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Finish Blocktimestamp
+ finish_transaction_hash:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Finish Transaction Hash
+ abort_blocktimestamp:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Abort Blocktimestamp
+ abort_transaction_hash:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Abort Transaction Hash
+ confirmed:
+ type: boolean
+ title: Confirmed
+ valid:
+ type: boolean
+ title: Valid
+ status:
+ $ref: '#/components/schemas/DeliveryStatus'
+ type: object
+ required:
+ - exchange_address
+ - delivery_id
+ - token_address
+ - buyer_address
+ - seller_address
+ - amount
+ - agent_address
+ - data
+ - create_blocktimestamp
+ - create_transaction_hash
+ - cancel_blocktimestamp
+ - cancel_transaction_hash
+ - confirm_blocktimestamp
+ - confirm_transaction_hash
+ - finish_blocktimestamp
+ - finish_transaction_hash
+ - abort_blocktimestamp
+ - abort_transaction_hash
+ - confirmed
+ - valid
+ - status
+ title: RetrieveDVPDeliveryResponse
+ description: Retrieve DVP delivery schema (Response)
+ RetrieveLedgerDetailsDataHistoryResponse:
+ properties:
+ account_address:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Account Address
+ name:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Name
+ address:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Address
+ amount:
+ type: integer
+ title: Amount
+ price:
+ type: integer
+ title: Price
+ balance:
+ type: integer
+ title: Balance
+ acquisition_date:
+ type: string
+ title: Acquisition Date
+ type: object
+ required:
+ - amount
+ - price
+ - balance
+ - acquisition_date
+ title: RetrieveLedgerDetailsDataHistoryResponse
+ description: Retrieve Ledger Details Data History schema (Response)
+ RetrieveLedgerDetailsDataResponse:
+ properties:
+ name:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Name
+ address:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Address
+ amount:
+ type: integer
+ title: Amount
+ price:
+ type: integer
+ title: Price
+ balance:
+ type: integer
+ title: Balance
+ acquisition_date:
+ type: string
+ title: Acquisition Date
+ type: object
+ required:
+ - name
+ - address
+ - amount
+ - price
+ - balance
+ - acquisition_date
+ title: RetrieveLedgerDetailsDataResponse
+ description: Retrieve Ledger Details Data schema (Response)
+ RetrieveLedgerDetailsHistoryResponse:
+ properties:
+ token_detail_type:
+ type: string
+ title: Token Detail Type
+ headers:
+ anyOf:
+ - items:
+ type: object
+ type: array
+ - type: 'null'
+ title: Headers
+ data:
+ items:
+ $ref: '#/components/schemas/RetrieveLedgerDetailsDataHistoryResponse'
+ type: array
+ title: Data
+ footers:
+ anyOf:
+ - items:
+ type: object
+ type: array
+ - type: 'null'
+ title: Footers
+ some_personal_info_not_registered:
+ type: boolean
+ title: Some Personal Info Not Registered
+ type: object
+ required:
+ - token_detail_type
+ - data
+ - some_personal_info_not_registered
+ title: RetrieveLedgerDetailsHistoryResponse
+ description: Retrieve Ledger Details History schema (Response)
+ RetrieveLedgerHistoryResponse:
+ properties:
+ created:
+ type: string
+ title: Created
+ token_name:
+ type: string
+ title: Token Name
+ currency:
+ type: string
+ title: Currency
+ headers:
+ anyOf:
+ - items:
+ type: object
+ type: array
+ - type: 'null'
+ title: Headers
+ details:
+ items:
+ $ref: '#/components/schemas/RetrieveLedgerDetailsHistoryResponse'
+ type: array
+ title: Details
+ footers:
+ anyOf:
+ - items:
+ type: object
+ type: array
+ - type: 'null'
+ title: Footers
+ type: object
+ required:
+ - created
+ - token_name
+ - currency
+ - details
+ title: RetrieveLedgerHistoryResponse
+ description: Retrieve Ledger History schema (Response)
+ RetrieveTokenHolderCollectionResponse:
+ properties:
+ token_address:
+ type: string
+ title: Token Address
+ block_number:
+ type: integer
+ title: Block Number
+ list_id:
+ type: string
+ title: List Id
+ description: UUID v4 required
+ status:
+ $ref: '#/components/schemas/TokenHolderBatchStatus'
+ type: object
+ required:
+ - token_address
+ - block_number
+ - list_id
+ - status
+ title: RetrieveTokenHolderCollectionResponse
+ description: Retrieve Token Holders Collection schema (RESPONSE)
+ RetrieveTokenHoldersListResponse:
+ properties:
+ status:
+ $ref: '#/components/schemas/TokenHolderBatchStatus'
+ holders:
+ items:
+ $ref: '#/components/schemas/TokenHoldersCollectionHolder'
+ type: array
+ title: Holders
+ type: object
+ required:
+ - status
+ - holders
+ title: RetrieveTokenHoldersListResponse
+ description: Retrieve Token Holders List schema (RESPONSE)
+ examples:
+ - holders:
+ - account_address: '0x85a8b8887a4bD76859751b10C8aC8EC5f3aA1bDB'
+ hold_balance: 30000
+ locked_balance: 0
+ status: done
+ ScheduleEventErrorMetaInfo:
+ properties:
+ scheduled_event_id:
+ type: string
+ title: Scheduled Event Id
+ token_address:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Token Address
+ token_type:
+ $ref: '#/components/schemas/TokenType'
+ type: object
+ required:
+ - scheduled_event_id
+ - token_type
+ title: ScheduleEventErrorMetaInfo
+ ScheduleEventErrorNotification:
+ properties:
+ notice_id:
+ type: string
+ title: Notice Id
+ issuer_address:
+ type: string
+ title: Issuer Address
+ priority:
+ type: integer
+ title: Priority
+ notice_code:
+ type: integer
+ maximum: 2.0
+ minimum: 0.0
+ title: Notice Code
+ description: |2
+ - 0: Issuer does not exist
+ - 1: Could not get the private key of the issuer
+ - 2: Failed to send transaction
+ created:
+ type: string
+ title: Created
+ notice_type:
+ type: string
+ enum:
+ - ScheduleEventError
+ const: ScheduleEventError
+ title: Notice Type
+ metainfo:
+ $ref: '#/components/schemas/ScheduleEventErrorMetaInfo'
+ type: object
+ required:
+ - notice_id
+ - issuer_address
+ - priority
+ - notice_code
+ - created
+ - notice_type
+ - metainfo
+ title: ScheduleEventErrorNotification
+ ScheduledEventIdResponse:
+ properties:
+ scheduled_event_id:
+ type: string
+ title: Scheduled Event Id
+ type: object
+ required:
+ - scheduled_event_id
+ title: ScheduledEventIdResponse
+ description: scheduled event (Response)
+ ScheduledEventResponse:
+ properties:
+ scheduled_event_id:
+ type: string
+ title: Scheduled Event Id
+ token_address:
+ type: string
+ title: Token Address
+ token_type:
+ $ref: '#/components/schemas/TokenType'
+ scheduled_datetime:
+ type: string
+ format: date-time
+ title: Scheduled Datetime
+ event_type:
+ $ref: '#/components/schemas/ScheduledEventType'
+ status:
+ type: integer
+ title: Status
+ data:
+ type: object
+ title: Data
+ created:
+ type: string
+ title: Created
+ type: object
+ required:
+ - scheduled_event_id
+ - token_address
+ - token_type
+ - scheduled_datetime
+ - event_type
+ - status
+ - data
+ - created
+ title: ScheduledEventResponse
+ description: scheduled event (Response)
+ ScheduledEventType:
+ type: string
+ enum:
+ - Update
+ const: Update
+ title: ScheduledEventType
+ SendTransactionErrorCode:
+ type: integer
+ enum:
+ - 2
+ const: 2
+ title: SendTransactionErrorCode
+ SendTransactionErrorMetainfo:
+ properties:
+ code:
+ allOf:
+ - $ref: '#/components/schemas/SendTransactionErrorCode'
+ examples:
+ - 2
+ title:
+ type: string
+ title: Title
+ examples:
+ - SendTransactionError
+ type: object
+ required:
+ - code
+ - title
+ title: SendTransactionErrorMetainfo
+ SendTransactionErrorResponse:
+ properties:
+ meta:
+ $ref: '#/components/schemas/SendTransactionErrorMetainfo'
+ detail:
+ type: string
+ title: Detail
+ type: object
+ required:
+ - meta
+ - detail
+ title: SendTransactionErrorResponse
+ ServiceUnavailableErrorCode:
+ type: integer
+ enum:
+ - 1
+ const: 1
+ title: ServiceUnavailableErrorCode
+ ServiceUnavailableErrorMetainfo:
+ properties:
+ code:
+ allOf:
+ - $ref: '#/components/schemas/ServiceUnavailableErrorCode'
+ examples:
+ - 1
+ title:
+ type: string
+ title: Title
+ examples:
+ - ServiceUnavailableError
+ type: object
+ required:
+ - code
+ - title
+ title: ServiceUnavailableErrorMetainfo
+ ServiceUnavailableErrorResponse:
+ properties:
+ meta:
+ $ref: '#/components/schemas/ServiceUnavailableErrorMetainfo'
+ detail:
+ type: string
+ title: Detail
+ type: object
+ required:
+ - meta
+ - detail
+ title: ServiceUnavailableErrorResponse
+ SortOrder:
+ type: integer
+ enum:
+ - 0
+ - 1
+ title: SortOrder
+ TokenAddressResponse:
+ properties:
+ token_address:
+ type: string
+ title: Token Address
+ token_status:
+ type: integer
+ title: Token Status
+ type: object
+ required:
+ - token_address
+ - token_status
+ title: TokenAddressResponse
+ description: token address
+ TokenHolderBatchStatus:
+ type: string
+ enum:
+ - pending
+ - done
+ - failed
+ title: TokenHolderBatchStatus
+ TokenHoldersCollectionHolder:
+ properties:
+ account_address:
+ type: string
+ title: Account Address
+ description: Account address of token holder.
+ hold_balance:
+ type: integer
+ title: Hold Balance
+ description: Amount of balance.This includes balance/pending_transfer/exchange_balance/exchange_commitment.
+ locked_balance:
+ type: integer
+ title: Locked Balance
+ description: Amount of locked balance.
+ type: object
+ required:
+ - account_address
+ - hold_balance
+ - locked_balance
+ title: TokenHoldersCollectionHolder
+ TokenOperationLogResponse:
+ properties:
+ original_contents:
+ anyOf:
+ - type: object
+ - type: 'null'
+ title: Original Contents
+ description: original attributes before update
+ modified_contents:
+ type: object
+ title: Modified Contents
+ description: update attributes
+ operation_category:
+ $ref: '#/components/schemas/TokenUpdateOperationCategory'
+ created:
+ type: string
+ format: date-time
+ title: Created
+ type: object
+ required:
+ - modified_contents
+ - operation_category
+ - created
+ title: TokenOperationLogResponse
+ TokenType:
+ type: string
+ enum:
+ - IbetStraightBond
+ - IbetShare
+ title: TokenType
+ TokenUpdateOperationCategory:
+ type: string
+ enum:
+ - Issue
+ - Update
+ title: TokenUpdateOperationCategory
+ description: Operation category of update token
+ TransferApprovalHistoryResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ transfer_approval_history:
+ items:
+ $ref: '#/components/schemas/TransferApprovalTokenResponse'
+ type: array
+ title: Transfer Approval History
+ type: object
+ required:
+ - result_set
+ - transfer_approval_history
+ title: TransferApprovalHistoryResponse
+ description: transfer approval token history
+ TransferApprovalInfoMetaInfo:
+ properties:
+ id:
+ type: integer
+ title: Id
+ token_address:
+ type: string
+ title: Token Address
+ token_type:
+ anyOf:
+ - $ref: '#/components/schemas/TokenType'
+ - type: 'null'
+ type: object
+ required:
+ - id
+ - token_address
+ title: TransferApprovalInfoMetaInfo
+ TransferApprovalInfoNotification:
+ properties:
+ notice_id:
+ type: string
+ title: Notice Id
+ issuer_address:
+ type: string
+ title: Issuer Address
+ priority:
+ type: integer
+ title: Priority
+ notice_code:
+ type: integer
+ maximum: 3.0
+ minimum: 0.0
+ title: Notice Code
+ description: |2
+ - 0: Apply for transfer
+ - 1: Cancel transfer
+ - 2: Approve transfer
+ - 3: Escrow finished (Only occurs in security token escrow)
+ created:
+ type: string
+ title: Created
+ notice_type:
+ type: string
+ enum:
+ - TransferApprovalInfo
+ const: TransferApprovalInfo
+ title: Notice Type
+ metainfo:
+ $ref: '#/components/schemas/TransferApprovalInfoMetaInfo'
+ type: object
+ required:
+ - notice_id
+ - issuer_address
+ - priority
+ - notice_code
+ - created
+ - notice_type
+ - metainfo
+ title: TransferApprovalInfoNotification
+ TransferApprovalResponse:
+ properties:
+ issuer_address:
+ type: string
+ title: Issuer Address
+ token_address:
+ type: string
+ title: Token Address
+ application_count:
+ type: integer
+ title: Application Count
+ unapproved_count:
+ type: integer
+ title: Unapproved Count
+ escrow_finished_count:
+ type: integer
+ title: Escrow Finished Count
+ transferred_count:
+ type: integer
+ title: Transferred Count
+ canceled_count:
+ type: integer
+ title: Canceled Count
+ type: object
+ required:
+ - issuer_address
+ - token_address
+ - application_count
+ - unapproved_count
+ - escrow_finished_count
+ - transferred_count
+ - canceled_count
+ title: TransferApprovalResponse
+ description: transfer approval data
+ TransferApprovalStatus:
+ type: integer
+ enum:
+ - 0
+ - 1
+ - 2
+ - 3
+ title: TransferApprovalStatus
+ TransferApprovalTokenDetailResponse:
+ properties:
+ id:
+ type: integer
+ title: Id
+ token_address:
+ type: string
+ title: Token Address
+ exchange_address:
+ type: string
+ title: Exchange Address
+ application_id:
+ type: integer
+ title: Application Id
+ from_address:
+ type: string
+ title: From Address
+ from_address_personal_information:
+ anyOf:
+ - $ref: '#/components/schemas/PersonalInfo'
+ - type: 'null'
+ to_address:
+ type: string
+ title: To Address
+ to_address_personal_information:
+ anyOf:
+ - $ref: '#/components/schemas/PersonalInfo'
+ - type: 'null'
+ amount:
+ type: integer
+ title: Amount
+ application_datetime:
+ type: string
+ title: Application Datetime
+ application_blocktimestamp:
+ type: string
+ title: Application Blocktimestamp
+ approval_datetime:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Approval Datetime
+ approval_blocktimestamp:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Approval Blocktimestamp
+ cancellation_blocktimestamp:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Cancellation Blocktimestamp
+ cancelled:
+ type: boolean
+ title: Cancelled
+ escrow_finished:
+ type: boolean
+ title: Escrow Finished
+ transfer_approved:
+ type: boolean
+ title: Transfer Approved
+ status:
+ type: integer
+ title: Status
+ issuer_cancelable:
+ type: boolean
+ title: Issuer Cancelable
+ type: object
+ required:
+ - id
+ - token_address
+ - exchange_address
+ - application_id
+ - from_address
+ - from_address_personal_information
+ - to_address
+ - to_address_personal_information
+ - amount
+ - application_datetime
+ - application_blocktimestamp
+ - approval_datetime
+ - approval_blocktimestamp
+ - cancellation_blocktimestamp
+ - cancelled
+ - escrow_finished
+ - transfer_approved
+ - status
+ - issuer_cancelable
+ title: TransferApprovalTokenDetailResponse
+ description: transfer approval token data
+ TransferApprovalTokenResponse:
+ properties:
+ id:
+ type: integer
+ title: Id
+ token_address:
+ type: string
+ title: Token Address
+ exchange_address:
+ type: string
+ title: Exchange Address
+ application_id:
+ type: integer
+ title: Application Id
+ from_address:
+ type: string
+ title: From Address
+ from_address_personal_information:
+ anyOf:
+ - $ref: '#/components/schemas/PersonalInfo'
+ - type: 'null'
+ to_address:
+ type: string
+ title: To Address
+ to_address_personal_information:
+ anyOf:
+ - $ref: '#/components/schemas/PersonalInfo'
+ - type: 'null'
+ amount:
+ type: integer
+ title: Amount
+ application_datetime:
+ type: string
+ title: Application Datetime
+ application_blocktimestamp:
+ type: string
+ title: Application Blocktimestamp
+ approval_datetime:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Approval Datetime
+ approval_blocktimestamp:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Approval Blocktimestamp
+ cancellation_blocktimestamp:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Cancellation Blocktimestamp
+ cancelled:
+ type: boolean
+ title: Cancelled
+ escrow_finished:
+ type: boolean
+ title: Escrow Finished
+ transfer_approved:
+ type: boolean
+ title: Transfer Approved
+ status:
+ type: integer
+ title: Status
+ issuer_cancelable:
+ type: boolean
+ title: Issuer Cancelable
+ type: object
+ required:
+ - id
+ - token_address
+ - exchange_address
+ - application_id
+ - from_address
+ - from_address_personal_information
+ - to_address
+ - to_address_personal_information
+ - amount
+ - application_datetime
+ - application_blocktimestamp
+ - approval_datetime
+ - approval_blocktimestamp
+ - cancellation_blocktimestamp
+ - cancelled
+ - escrow_finished
+ - transfer_approved
+ - status
+ - issuer_cancelable
+ title: TransferApprovalTokenResponse
+ description: transfer approval token data
+ TransferApprovalsResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ transfer_approvals:
+ items:
+ $ref: '#/components/schemas/TransferApprovalResponse'
+ type: array
+ title: Transfer Approvals
+ type: object
+ required:
+ - result_set
+ - transfer_approvals
+ title: TransferApprovalsResponse
+ description: transfer approvals
+ TransferHistoryResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ transfer_history:
+ items:
+ $ref: '#/components/schemas/TransferResponse'
+ type: array
+ title: Transfer History
+ type: object
+ required:
+ - result_set
+ - transfer_history
+ title: TransferHistoryResponse
+ description: transfer history
+ TransferResponse:
+ properties:
+ transaction_hash:
+ type: string
+ title: Transaction Hash
+ token_address:
+ type: string
+ title: Token Address
+ from_address:
+ type: string
+ title: From Address
+ from_address_personal_information:
+ anyOf:
+ - $ref: '#/components/schemas/PersonalInfo'
+ - type: 'null'
+ to_address:
+ type: string
+ title: To Address
+ to_address_personal_information:
+ anyOf:
+ - $ref: '#/components/schemas/PersonalInfo'
+ - type: 'null'
+ amount:
+ type: integer
+ title: Amount
+ source_event:
+ allOf:
+ - $ref: '#/components/schemas/TransferSourceEventType'
+ description: Source Event
+ data:
+ anyOf:
+ - type: object
+ - type: 'null'
+ title: Data
+ description: Event data
+ block_timestamp:
+ type: string
+ title: Block Timestamp
+ type: object
+ required:
+ - transaction_hash
+ - token_address
+ - from_address
+ - from_address_personal_information
+ - to_address
+ - to_address_personal_information
+ - amount
+ - source_event
+ - data
+ - block_timestamp
+ title: TransferResponse
+ description: transfer data
+ TransferSourceEventType:
+ type: string
+ enum:
+ - Transfer
+ - Unlock
+ title: TransferSourceEventType
+ TxData:
+ properties:
+ hash:
+ type: string
+ title: Hash
+ description: Transaction hash
+ block_hash:
+ type: string
+ title: Block Hash
+ block_number:
+ type: integer
+ minimum: 0.0
+ title: Block Number
+ transaction_index:
+ type: integer
+ minimum: 0.0
+ title: Transaction Index
+ from_address:
+ type: string
+ title: From Address
+ to_address:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: To Address
+ type: object
+ required:
+ - hash
+ - block_hash
+ - block_number
+ - transaction_index
+ - from_address
+ - to_address
+ title: TxData
+ TxDataDetail:
+ properties:
+ hash:
+ type: string
+ title: Hash
+ description: Transaction hash
+ block_hash:
+ type: string
+ title: Block Hash
+ block_number:
+ type: integer
+ minimum: 0.0
+ title: Block Number
+ transaction_index:
+ type: integer
+ minimum: 0.0
+ title: Transaction Index
+ from_address:
+ type: string
+ title: From Address
+ to_address:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: To Address
+ contract_name:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Contract Name
+ contract_function:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Contract Function
+ contract_parameters:
+ anyOf:
+ - type: object
+ - type: 'null'
+ title: Contract Parameters
+ gas:
+ type: integer
+ minimum: 0.0
+ title: Gas
+ gas_price:
+ type: integer
+ minimum: 0.0
+ title: Gas Price
+ value:
+ type: integer
+ minimum: 0.0
+ title: Value
+ nonce:
+ type: integer
+ minimum: 0.0
+ title: Nonce
+ type: object
+ required:
+ - hash
+ - block_hash
+ - block_number
+ - transaction_index
+ - from_address
+ - to_address
+ - contract_name
+ - contract_function
+ - contract_parameters
+ - gas
+ - gas_price
+ - value
+ - nonce
+ title: TxDataDetail
+ TxDataListResponse:
+ properties:
+ result_set:
+ $ref: '#/components/schemas/ResultSet'
+ tx_data:
+ items:
+ $ref: '#/components/schemas/TxData'
+ type: array
+ title: Tx Data
+ type: object
+ required:
+ - result_set
+ - tx_data
+ title: TxDataListResponse
+ TxDataResponse:
+ allOf:
+ - $ref: '#/components/schemas/TxDataDetail'
+ title: TxDataResponse
+ UnlockInfoMetaInfo:
+ properties:
+ token_address:
+ type: string
+ title: Token Address
+ token_type:
+ $ref: '#/components/schemas/TokenType'
+ lock_address:
+ type: string
+ title: Lock Address
+ account_address:
+ type: string
+ title: Account Address
+ recipient_address:
+ type: string
+ title: Recipient Address
+ value:
+ type: integer
+ title: Value
+ data:
+ type: object
+ title: Data
+ type: object
+ required:
+ - token_address
+ - token_type
+ - lock_address
+ - account_address
+ - recipient_address
+ - value
+ - data
+ title: UnlockInfoMetaInfo
+ UnlockInfoNotification:
+ properties:
+ notice_id:
+ type: string
+ title: Notice Id
+ issuer_address:
+ type: string
+ title: Issuer Address
+ priority:
+ type: integer
+ title: Priority
+ notice_code:
+ type: integer
+ maximum: 0.0
+ minimum: 0.0
+ title: Notice Code
+ description: " - 0: Balance is unlocked\n"
+ created:
+ type: string
+ title: Created
+ notice_type:
+ type: string
+ enum:
+ - UnlockInfo
+ const: UnlockInfo
+ title: Notice Type
+ metainfo:
+ $ref: '#/components/schemas/UnlockInfoMetaInfo'
+ type: object
+ required:
+ - notice_id
+ - issuer_address
+ - priority
+ - notice_code
+ - created
+ - notice_type
+ - metainfo
+ title: UnlockInfoNotification
+ UpdateFreezeLogRequest:
+ properties:
+ account_address:
+ type: string
+ title: Account Address
+ description: Logging account address
+ eoa_password:
+ type: string
+ title: Eoa Password
+ description: Logging account key file password
+ log_message:
+ type: string
+ title: Log Message
+ description: Log message
+ type: object
+ required:
+ - account_address
+ - eoa_password
+ - log_message
+ title: UpdateFreezeLogRequest
+ description: Update freeze log schema (REQUEST)
+ UpdateTransferApprovalOperationType:
+ type: string
+ enum:
+ - approve
+ - cancel
+ title: UpdateTransferApprovalOperationType
+ UpdateTransferApprovalRequest:
+ properties:
+ operation_type:
+ $ref: '#/components/schemas/UpdateTransferApprovalOperationType'
+ type: object
+ required:
+ - operation_type
+ title: UpdateTransferApprovalRequest
+ description: Update Transfer Approval schema (Request)
+ UploadFileRequest:
+ properties:
+ relation:
+ anyOf:
+ - type: string
+ maxLength: 50
+ - type: 'null'
+ title: Relation
+ file_name:
+ type: string
+ maxLength: 256
+ title: File Name
+ content:
+ type: string
+ title: Content
+ description: |-
+ Base64-encoded content.
+ Max length of binary data before encoding is 100000000.
+ description:
+ anyOf:
+ - type: string
+ maxLength: 1000
+ - type: 'null'
+ title: Description
+ label:
+ anyOf:
+ - type: string
+ maxLength: 200
+ - type: 'null'
+ title: Label
+ type: object
+ required:
+ - file_name
+ - content
+ title: UploadFileRequest
+ description: Upload File schema (Request)
+ ValidationError:
+ properties:
+ loc:
+ items:
+ anyOf:
+ - type: string
+ - type: integer
+ type: array
+ title: Location
+ msg:
+ type: string
+ title: Message
+ type:
+ type: string
+ title: Error Type
+ type: object
+ required:
+ - loc
+ - msg
+ - type
+ title: ValidationError
+ ValueOperator:
+ type: integer
+ enum:
+ - 0
+ - 1
+ - 2
+ title: ValueOperator
+tags:
+ - name: root
+ description: ''
+ - name: common
+ description: Common functions
+ - name: account
+ description: Issuer account management
+ - name: notification
+ description: Notifications for accounts
+ - name: token_common
+ description: Common functions for tokens
+ - name: bond
+ description: Bond token management
+ - name: share
+ description: Share token management
+ - name: utility
+ description: Utility functions
+ - name: messaging
+ description: Messaging functions with external systems
+ - name: blockchain_explorer
+ description: Blockchain explorer
diff --git a/hardhat.config.js b/hardhat.config.js
new file mode 100644
index 00000000..6a1338f1
--- /dev/null
+++ b/hardhat.config.js
@@ -0,0 +1,15 @@
+/** @type import('hardhat/config').HardhatUserConfig */
+module.exports = {
+ networks: {
+ hardhat: {
+ chainId: 2017,
+ gasPrice: 0,
+ blockGasLimit: 800000000,
+ hardfork: "berlin",
+ throwOnTransactionFailures: false,
+ throwOnCallFailures: false,
+ allowBlocksWithSameTimestamp: true
+ },
+ },
+ solidity: "0.8.23",
+};
\ No newline at end of file
diff --git a/migrations/versions/0656c408ebbb_v24_6_0_feature_627.py b/migrations/versions/0656c408ebbb_v24_6_0_feature_627.py
new file mode 100644
index 00000000..234d5078
--- /dev/null
+++ b/migrations/versions/0656c408ebbb_v24_6_0_feature_627.py
@@ -0,0 +1,74 @@
+"""v24_6_0_feature_627
+
+Revision ID: 0656c408ebbb
+Revises: 5954db6ba5f4
+Create Date: 2024-05-14 09:40:35.862686
+
+"""
+
+from alembic import op
+import sqlalchemy as sa
+
+
+from app.database import get_db_schema
+
+# revision identifiers, used by Alembic.
+revision = "0656c408ebbb"
+down_revision = "5954db6ba5f4"
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ op.create_table(
+ "idx_personal_info_history",
+ sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
+ sa.Column("account_address", sa.String(length=42), nullable=True),
+ sa.Column("issuer_address", sa.String(length=42), nullable=True),
+ sa.Column("event_type", sa.String(length=10), nullable=False),
+ sa.Column("personal_info", sa.JSON(), nullable=False),
+ sa.Column("created", sa.DateTime(), nullable=True),
+ sa.Column("modified", sa.DateTime(), nullable=True),
+ sa.PrimaryKeyConstraint("id"),
+ schema=get_db_schema(),
+ )
+ op.create_index(
+ op.f("ix_idx_personal_info_history_account_address"),
+ "idx_personal_info_history",
+ ["account_address"],
+ unique=False,
+ schema=get_db_schema(),
+ )
+ op.create_index(
+ op.f("ix_idx_personal_info_history_event_type"),
+ "idx_personal_info_history",
+ ["event_type"],
+ unique=False,
+ schema=get_db_schema(),
+ )
+ op.create_index(
+ op.f("ix_idx_personal_info_history_issuer_address"),
+ "idx_personal_info_history",
+ ["issuer_address"],
+ unique=False,
+ schema=get_db_schema(),
+ )
+
+
+def downgrade():
+ op.drop_index(
+ op.f("ix_idx_personal_info_history_issuer_address"),
+ table_name="idx_personal_info_history",
+ schema=get_db_schema(),
+ )
+ op.drop_index(
+ op.f("ix_idx_personal_info_history_event_type"),
+ table_name="idx_personal_info_history",
+ schema=get_db_schema(),
+ )
+ op.drop_index(
+ op.f("ix_idx_personal_info_history_account_address"),
+ table_name="idx_personal_info_history",
+ schema=get_db_schema(),
+ )
+ op.drop_table("idx_personal_info_history", schema=get_db_schema())
diff --git a/migrations/versions/346d0e814893_v24_6_0_feature_606_1.py b/migrations/versions/346d0e814893_v24_6_0_feature_606_1.py
new file mode 100644
index 00000000..96efde65
--- /dev/null
+++ b/migrations/versions/346d0e814893_v24_6_0_feature_606_1.py
@@ -0,0 +1,185 @@
+"""v24_6_0_feature_606_1
+
+Revision ID: 346d0e814893
+Revises: a748dd5d4119
+Create Date: 2024-04-11 14:29:27.434855
+
+"""
+
+from alembic import op
+import sqlalchemy as sa
+
+
+from app.database import get_db_schema
+
+# revision identifiers, used by Alembic.
+revision = "346d0e814893"
+down_revision = "a748dd5d4119"
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ op.create_table(
+ "idx_delivery",
+ sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
+ sa.Column("exchange_address", sa.String(length=42), nullable=False),
+ sa.Column("delivery_id", sa.BigInteger(), nullable=False),
+ sa.Column("token_address", sa.String(length=42), nullable=False),
+ sa.Column("buyer_address", sa.String(length=42), nullable=False),
+ sa.Column("seller_address", sa.String(length=42), nullable=False),
+ sa.Column("amount", sa.BigInteger(), nullable=False),
+ sa.Column("agent_address", sa.String(length=42), nullable=False),
+ sa.Column("data", sa.Text(), nullable=False),
+ sa.Column("create_blocktimestamp", sa.DateTime(), nullable=False),
+ sa.Column("create_transaction_hash", sa.String(length=66), nullable=False),
+ sa.Column("cancel_blocktimestamp", sa.DateTime(), nullable=True),
+ sa.Column("cancel_transaction_hash", sa.String(length=66), nullable=True),
+ sa.Column("confirm_blocktimestamp", sa.DateTime(), nullable=True),
+ sa.Column("confirm_transaction_hash", sa.String(length=66), nullable=True),
+ sa.Column("finish_blocktimestamp", sa.DateTime(), nullable=True),
+ sa.Column("finish_transaction_hash", sa.String(length=66), nullable=True),
+ sa.Column("abort_blocktimestamp", sa.DateTime(), nullable=True),
+ sa.Column("abort_transaction_hash", sa.String(length=66), nullable=True),
+ sa.Column("confirmed", sa.Boolean(), nullable=False),
+ sa.Column("valid", sa.Boolean(), nullable=False),
+ sa.Column("status", sa.BigInteger(), nullable=False),
+ sa.Column("created", sa.DateTime(), nullable=True),
+ sa.Column("modified", sa.DateTime(), nullable=True),
+ sa.PrimaryKeyConstraint("id"),
+ schema=get_db_schema(),
+ )
+ op.create_index(
+ op.f("ix_idx_delivery_abort_transaction_hash"),
+ "idx_delivery",
+ ["abort_transaction_hash"],
+ unique=False,
+ schema=get_db_schema(),
+ )
+ op.create_index(
+ op.f("ix_idx_delivery_agent_address"),
+ "idx_delivery",
+ ["agent_address"],
+ unique=False,
+ schema=get_db_schema(),
+ )
+ op.create_index(
+ op.f("ix_idx_delivery_cancel_transaction_hash"),
+ "idx_delivery",
+ ["cancel_transaction_hash"],
+ unique=False,
+ schema=get_db_schema(),
+ )
+ op.create_index(
+ op.f("ix_idx_delivery_confirm_transaction_hash"),
+ "idx_delivery",
+ ["confirm_transaction_hash"],
+ unique=False,
+ schema=get_db_schema(),
+ )
+ op.create_index(
+ op.f("ix_idx_delivery_create_transaction_hash"),
+ "idx_delivery",
+ ["create_transaction_hash"],
+ unique=False,
+ schema=get_db_schema(),
+ )
+ op.create_index(
+ op.f("ix_idx_delivery_delivery_id"),
+ "idx_delivery",
+ ["delivery_id"],
+ unique=False,
+ schema=get_db_schema(),
+ )
+ op.create_index(
+ op.f("ix_idx_delivery_exchange_address"),
+ "idx_delivery",
+ ["exchange_address"],
+ unique=False,
+ schema=get_db_schema(),
+ )
+ op.create_index(
+ op.f("ix_idx_delivery_finish_transaction_hash"),
+ "idx_delivery",
+ ["finish_transaction_hash"],
+ unique=False,
+ schema=get_db_schema(),
+ )
+ op.create_index(
+ op.f("ix_idx_delivery_seller_address"),
+ "idx_delivery",
+ ["seller_address"],
+ unique=False,
+ schema=get_db_schema(),
+ )
+ op.create_index(
+ op.f("ix_idx_delivery_token_address"),
+ "idx_delivery",
+ ["token_address"],
+ unique=False,
+ schema=get_db_schema(),
+ )
+ op.create_table(
+ "idx_delivery_block_number",
+ sa.Column("exchange_address", sa.String(length=42), nullable=False),
+ sa.Column("latest_block_number", sa.BigInteger(), nullable=False),
+ sa.Column("created", sa.DateTime(), nullable=True),
+ sa.Column("modified", sa.DateTime(), nullable=True),
+ sa.PrimaryKeyConstraint("exchange_address"),
+ schema=get_db_schema(),
+ )
+
+
+def downgrade():
+ op.drop_table("idx_delivery_block_number", schema=get_db_schema())
+ op.drop_index(
+ op.f("ix_idx_delivery_token_address"),
+ table_name="idx_delivery",
+ schema=get_db_schema(),
+ )
+ op.drop_index(
+ op.f("ix_idx_delivery_seller_address"),
+ table_name="idx_delivery",
+ schema=get_db_schema(),
+ )
+ op.drop_index(
+ op.f("ix_idx_delivery_finish_transaction_hash"),
+ table_name="idx_delivery",
+ schema=get_db_schema(),
+ )
+ op.drop_index(
+ op.f("ix_idx_delivery_exchange_address"),
+ table_name="idx_delivery",
+ schema=get_db_schema(),
+ )
+ op.drop_index(
+ op.f("ix_idx_delivery_delivery_id"),
+ table_name="idx_delivery",
+ schema=get_db_schema(),
+ )
+ op.drop_index(
+ op.f("ix_idx_delivery_create_transaction_hash"),
+ table_name="idx_delivery",
+ schema=get_db_schema(),
+ )
+ op.drop_index(
+ op.f("ix_idx_delivery_confirm_transaction_hash"),
+ table_name="idx_delivery",
+ schema=get_db_schema(),
+ )
+ op.drop_index(
+ op.f("ix_idx_delivery_cancel_transaction_hash"),
+ table_name="idx_delivery",
+ schema=get_db_schema(),
+ )
+ op.drop_index(
+ op.f("ix_idx_delivery_agent_address"),
+ table_name="idx_delivery",
+ schema=get_db_schema(),
+ )
+ op.drop_index(
+ op.f("ix_idx_delivery_abort_transaction_hash"),
+ table_name="idx_delivery",
+ schema=get_db_schema(),
+ )
+ op.drop_table("idx_delivery", schema=get_db_schema())
diff --git a/migrations/versions/4704529e8fe0_v24_6_0_feature_637.py b/migrations/versions/4704529e8fe0_v24_6_0_feature_637.py
new file mode 100644
index 00000000..b25acf99
--- /dev/null
+++ b/migrations/versions/4704529e8fe0_v24_6_0_feature_637.py
@@ -0,0 +1,37 @@
+"""v24_6_0_feature_637
+
+Revision ID: 4704529e8fe0
+Revises: 0656c408ebbb
+Create Date: 2024-06-04 17:46:03.131011
+
+"""
+
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy import delete
+
+
+from app.database import get_db_schema
+from app.model.db import IDXPersonalInfoHistory
+
+# revision identifiers, used by Alembic.
+revision = "4704529e8fe0"
+down_revision = "0656c408ebbb"
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ # Delete all `idx_personal_info_history` data
+ op.get_bind().execute(delete(IDXPersonalInfoHistory))
+ op.add_column(
+ "idx_personal_info_history",
+ sa.Column("block_timestamp", sa.DateTime(), nullable=True),
+ schema=get_db_schema(),
+ )
+
+
+def downgrade():
+ op.drop_column(
+ "idx_personal_info_history", "block_timestamp", schema=get_db_schema()
+ )
diff --git a/migrations/versions/5954db6ba5f4_v24_6_0_feature_606_2.py b/migrations/versions/5954db6ba5f4_v24_6_0_feature_606_2.py
new file mode 100644
index 00000000..1be2d026
--- /dev/null
+++ b/migrations/versions/5954db6ba5f4_v24_6_0_feature_606_2.py
@@ -0,0 +1,37 @@
+"""v24_6_0_feature_606_2
+
+Revision ID: 5954db6ba5f4
+Revises: 346d0e814893
+Create Date: 2024-04-12 21:45:53.594057
+
+"""
+
+from alembic import op
+import sqlalchemy as sa
+
+
+from app.database import get_db_schema
+
+# revision identifiers, used by Alembic.
+revision = "5954db6ba5f4"
+down_revision = "346d0e814893"
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ op.create_table(
+ "dvp_agent_account",
+ sa.Column("account_address", sa.String(length=42), nullable=False),
+ sa.Column("keyfile", sa.JSON(), nullable=True),
+ sa.Column("eoa_password", sa.String(length=2000), nullable=True),
+ sa.Column("is_deleted", sa.Boolean(), nullable=True),
+ sa.Column("created", sa.DateTime(), nullable=True),
+ sa.Column("modified", sa.DateTime(), nullable=True),
+ sa.PrimaryKeyConstraint("account_address"),
+ schema=get_db_schema(),
+ )
+
+
+def downgrade():
+ op.drop_table("dvp_agent_account", schema=get_db_schema())
diff --git a/migrations/versions/a748dd5d4119_v24_6_0_feature_610.py b/migrations/versions/a748dd5d4119_v24_6_0_feature_610.py
new file mode 100644
index 00000000..72815ce8
--- /dev/null
+++ b/migrations/versions/a748dd5d4119_v24_6_0_feature_610.py
@@ -0,0 +1,27 @@
+"""v24_6_0_feature_610
+
+Revision ID: a748dd5d4119
+Revises: cb24da38646e
+Create Date: 2024-04-07 00:40:00.047349
+
+"""
+
+from alembic import op
+from sqlalchemy import delete
+
+from app.model.db import TokenCache
+
+# revision identifiers, used by Alembic.
+revision = "a748dd5d4119"
+down_revision = "cb24da38646e"
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ # Delete all `token_cache` data
+ op.get_bind().execute(delete(TokenCache))
+
+
+def downgrade():
+ pass
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 00000000..e8d28e1b
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,3459 @@
+{
+ "name": "ibet-Prime",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "devDependencies": {
+ "hardhat": "^2.22.3"
+ }
+ },
+ "node_modules/@ethersproject/abi": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz",
+ "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/address": "^5.7.0",
+ "@ethersproject/bignumber": "^5.7.0",
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/constants": "^5.7.0",
+ "@ethersproject/hash": "^5.7.0",
+ "@ethersproject/keccak256": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0",
+ "@ethersproject/properties": "^5.7.0",
+ "@ethersproject/strings": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/abstract-provider": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz",
+ "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/bignumber": "^5.7.0",
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0",
+ "@ethersproject/networks": "^5.7.0",
+ "@ethersproject/properties": "^5.7.0",
+ "@ethersproject/transactions": "^5.7.0",
+ "@ethersproject/web": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/abstract-signer": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz",
+ "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/abstract-provider": "^5.7.0",
+ "@ethersproject/bignumber": "^5.7.0",
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0",
+ "@ethersproject/properties": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/address": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz",
+ "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/bignumber": "^5.7.0",
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/keccak256": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0",
+ "@ethersproject/rlp": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/base64": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz",
+ "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/bytes": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/bignumber": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz",
+ "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0",
+ "bn.js": "^5.2.1"
+ }
+ },
+ "node_modules/@ethersproject/bytes": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz",
+ "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/logger": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/constants": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz",
+ "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/bignumber": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/hash": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz",
+ "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/abstract-signer": "^5.7.0",
+ "@ethersproject/address": "^5.7.0",
+ "@ethersproject/base64": "^5.7.0",
+ "@ethersproject/bignumber": "^5.7.0",
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/keccak256": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0",
+ "@ethersproject/properties": "^5.7.0",
+ "@ethersproject/strings": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/keccak256": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz",
+ "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/bytes": "^5.7.0",
+ "js-sha3": "0.8.0"
+ }
+ },
+ "node_modules/@ethersproject/logger": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz",
+ "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ]
+ },
+ "node_modules/@ethersproject/networks": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz",
+ "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/logger": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/properties": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz",
+ "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/logger": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/rlp": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz",
+ "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/signing-key": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz",
+ "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0",
+ "@ethersproject/properties": "^5.7.0",
+ "bn.js": "^5.2.1",
+ "elliptic": "6.5.4",
+ "hash.js": "1.1.7"
+ }
+ },
+ "node_modules/@ethersproject/strings": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz",
+ "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/constants": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/transactions": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz",
+ "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/address": "^5.7.0",
+ "@ethersproject/bignumber": "^5.7.0",
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/constants": "^5.7.0",
+ "@ethersproject/keccak256": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0",
+ "@ethersproject/properties": "^5.7.0",
+ "@ethersproject/rlp": "^5.7.0",
+ "@ethersproject/signing-key": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/web": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz",
+ "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/base64": "^5.7.0",
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0",
+ "@ethersproject/properties": "^5.7.0",
+ "@ethersproject/strings": "^5.7.0"
+ }
+ },
+ "node_modules/@fastify/busboy": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz",
+ "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@metamask/eth-sig-util": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz",
+ "integrity": "sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==",
+ "dev": true,
+ "dependencies": {
+ "ethereumjs-abi": "^0.6.8",
+ "ethereumjs-util": "^6.2.1",
+ "ethjs-util": "^0.1.6",
+ "tweetnacl": "^1.0.3",
+ "tweetnacl-util": "^0.15.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/@noble/hashes": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz",
+ "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ]
+ },
+ "node_modules/@noble/secp256k1": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz",
+ "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ]
+ },
+ "node_modules/@nomicfoundation/edr": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.3.5.tgz",
+ "integrity": "sha512-dPSM9DuI1sr71gqWUMgLo8MjHQWO4+WNDm3iWaT6P4vUFJReZX5qwA5X+3UwIPBry8GvNY084u7yWUvB3/8rqA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 18"
+ },
+ "optionalDependencies": {
+ "@nomicfoundation/edr-darwin-arm64": "0.3.5",
+ "@nomicfoundation/edr-darwin-x64": "0.3.5",
+ "@nomicfoundation/edr-linux-arm64-gnu": "0.3.5",
+ "@nomicfoundation/edr-linux-arm64-musl": "0.3.5",
+ "@nomicfoundation/edr-linux-x64-gnu": "0.3.5",
+ "@nomicfoundation/edr-linux-x64-musl": "0.3.5",
+ "@nomicfoundation/edr-win32-x64-msvc": "0.3.5"
+ }
+ },
+ "node_modules/@nomicfoundation/edr-darwin-arm64": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.3.5.tgz",
+ "integrity": "sha512-gIXUIiPMUy6roLHpNlxf15DumU7/YhffUf7XIB+WUjMecaySfTGyZsTGnCMJZqrDyiYqWPyPKwCV/2u/jqFAUg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@nomicfoundation/edr-darwin-x64": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.3.5.tgz",
+ "integrity": "sha512-0MrpOCXUK8gmplpYZ2Cy0holHEylvWoNeecFcrP2WJ5DLQzrB23U5JU2MvUzOJ7aL76Za1VXNBWi/UeTWdHM+w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@nomicfoundation/edr-linux-arm64-gnu": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.3.5.tgz",
+ "integrity": "sha512-aw9f7AZMiY1dZFNePJGKho2k+nEgFgzUAyyukiKfSqUIMXoFXMf1U3Ujv848czrSq9c5XGcdDa2xnEf3daU3xg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@nomicfoundation/edr-linux-arm64-musl": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.3.5.tgz",
+ "integrity": "sha512-cVFRQjyABBlsbDj+XTczYBfrCHprZ6YNzN8gGGSqAh+UGIJkAIRomK6ar27GyJLNx3HkgbuDoi/9kA0zOo/95w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@nomicfoundation/edr-linux-x64-gnu": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.3.5.tgz",
+ "integrity": "sha512-CjOg85DfR1Vt0fQWn5U0qi26DATK9tVzo3YOZEyI0JBsnqvk43fUTPv3uUAWBrPIRg5O5kOc9xG13hSpCBBxBg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@nomicfoundation/edr-linux-x64-musl": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.3.5.tgz",
+ "integrity": "sha512-hvX8bBGpBydAVevzK8jsu2FlqVZK1RrCyTX6wGHnltgMuBaoGLHYtNHiFpteOaJw2byYMiORc2bvj+98LhJ0Ew==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@nomicfoundation/edr-win32-x64-msvc": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.3.5.tgz",
+ "integrity": "sha512-IJXjW13DY5UPsx/eG5DGfXtJ7Ydwrvw/BTZ2Y93lRLHzszVpSmeVmlxjZP5IW2afTSgMLaAAsqNw4NhppRGN8A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@nomicfoundation/ethereumjs-common": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz",
+ "integrity": "sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==",
+ "dev": true,
+ "dependencies": {
+ "@nomicfoundation/ethereumjs-util": "9.0.4"
+ }
+ },
+ "node_modules/@nomicfoundation/ethereumjs-rlp": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz",
+ "integrity": "sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==",
+ "dev": true,
+ "bin": {
+ "rlp": "bin/rlp.cjs"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@nomicfoundation/ethereumjs-tx": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz",
+ "integrity": "sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==",
+ "dev": true,
+ "dependencies": {
+ "@nomicfoundation/ethereumjs-common": "4.0.4",
+ "@nomicfoundation/ethereumjs-rlp": "5.0.4",
+ "@nomicfoundation/ethereumjs-util": "9.0.4",
+ "ethereum-cryptography": "0.1.3"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "c-kzg": "^2.1.2"
+ },
+ "peerDependenciesMeta": {
+ "c-kzg": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@nomicfoundation/ethereumjs-tx/node_modules/ethereum-cryptography": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz",
+ "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/pbkdf2": "^3.0.0",
+ "@types/secp256k1": "^4.0.1",
+ "blakejs": "^1.1.0",
+ "browserify-aes": "^1.2.0",
+ "bs58check": "^2.1.2",
+ "create-hash": "^1.2.0",
+ "create-hmac": "^1.1.7",
+ "hash.js": "^1.1.7",
+ "keccak": "^3.0.0",
+ "pbkdf2": "^3.0.17",
+ "randombytes": "^2.1.0",
+ "safe-buffer": "^5.1.2",
+ "scrypt-js": "^3.0.0",
+ "secp256k1": "^4.0.1",
+ "setimmediate": "^1.0.5"
+ }
+ },
+ "node_modules/@nomicfoundation/ethereumjs-util": {
+ "version": "9.0.4",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz",
+ "integrity": "sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==",
+ "dev": true,
+ "dependencies": {
+ "@nomicfoundation/ethereumjs-rlp": "5.0.4",
+ "ethereum-cryptography": "0.1.3"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "c-kzg": "^2.1.2"
+ },
+ "peerDependenciesMeta": {
+ "c-kzg": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@nomicfoundation/ethereumjs-util/node_modules/ethereum-cryptography": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz",
+ "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/pbkdf2": "^3.0.0",
+ "@types/secp256k1": "^4.0.1",
+ "blakejs": "^1.1.0",
+ "browserify-aes": "^1.2.0",
+ "bs58check": "^2.1.2",
+ "create-hash": "^1.2.0",
+ "create-hmac": "^1.1.7",
+ "hash.js": "^1.1.7",
+ "keccak": "^3.0.0",
+ "pbkdf2": "^3.0.17",
+ "randombytes": "^2.1.0",
+ "safe-buffer": "^5.1.2",
+ "scrypt-js": "^3.0.0",
+ "secp256k1": "^4.0.1",
+ "setimmediate": "^1.0.5"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz",
+ "integrity": "sha512-1LMtXj1puAxyFusBgUIy5pZk3073cNXYnXUpuNKFghHbIit/xZgbk0AokpUADbNm3gyD6bFWl3LRFh3dhVdREg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 12"
+ },
+ "optionalDependencies": {
+ "@nomicfoundation/solidity-analyzer-darwin-arm64": "0.1.1",
+ "@nomicfoundation/solidity-analyzer-darwin-x64": "0.1.1",
+ "@nomicfoundation/solidity-analyzer-freebsd-x64": "0.1.1",
+ "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": "0.1.1",
+ "@nomicfoundation/solidity-analyzer-linux-arm64-musl": "0.1.1",
+ "@nomicfoundation/solidity-analyzer-linux-x64-gnu": "0.1.1",
+ "@nomicfoundation/solidity-analyzer-linux-x64-musl": "0.1.1",
+ "@nomicfoundation/solidity-analyzer-win32-arm64-msvc": "0.1.1",
+ "@nomicfoundation/solidity-analyzer-win32-ia32-msvc": "0.1.1",
+ "@nomicfoundation/solidity-analyzer-win32-x64-msvc": "0.1.1"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer-darwin-arm64": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.1.tgz",
+ "integrity": "sha512-KcTodaQw8ivDZyF+D76FokN/HdpgGpfjc/gFCImdLUyqB6eSWVaZPazMbeAjmfhx3R0zm/NYVzxwAokFKgrc0w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer-darwin-x64": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.1.tgz",
+ "integrity": "sha512-XhQG4BaJE6cIbjAVtzGOGbK3sn1BO9W29uhk9J8y8fZF1DYz0Doj8QDMfpMu+A6TjPDs61lbsmeYodIDnfveSA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer-freebsd-x64": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-freebsd-x64/-/solidity-analyzer-freebsd-x64-0.1.1.tgz",
+ "integrity": "sha512-GHF1VKRdHW3G8CndkwdaeLkVBi5A9u2jwtlS7SLhBc8b5U/GcoL39Q+1CSO3hYqePNP+eV5YI7Zgm0ea6kMHoA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-gnu": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.1.tgz",
+ "integrity": "sha512-g4Cv2fO37ZsUENQ2vwPnZc2zRenHyAxHcyBjKcjaSmmkKrFr64yvzeNO8S3GBFCo90rfochLs99wFVGT/0owpg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-musl": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.1.tgz",
+ "integrity": "sha512-WJ3CE5Oek25OGE3WwzK7oaopY8xMw9Lhb0mlYuJl/maZVo+WtP36XoQTb7bW/i8aAdHW5Z+BqrHMux23pvxG3w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-gnu": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.1.tgz",
+ "integrity": "sha512-5WN7leSr5fkUBBjE4f3wKENUy9HQStu7HmWqbtknfXkkil+eNWiBV275IOlpXku7v3uLsXTOKpnnGHJYI2qsdA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-musl": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.1.tgz",
+ "integrity": "sha512-KdYMkJOq0SYPQMmErv/63CwGwMm5XHenEna9X9aB8mQmhDBrYrlAOSsIPgFCUSL0hjxE3xHP65/EPXR/InD2+w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer-win32-arm64-msvc": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-arm64-msvc/-/solidity-analyzer-win32-arm64-msvc-0.1.1.tgz",
+ "integrity": "sha512-VFZASBfl4qiBYwW5xeY20exWhmv6ww9sWu/krWSesv3q5hA0o1JuzmPHR4LPN6SUZj5vcqci0O6JOL8BPw+APg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer-win32-ia32-msvc": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-ia32-msvc/-/solidity-analyzer-win32-ia32-msvc-0.1.1.tgz",
+ "integrity": "sha512-JnFkYuyCSA70j6Si6cS1A9Gh1aHTEb8kOTBApp/c7NRTFGNMH8eaInKlyuuiIbvYFhlXW4LicqyYuWNNq9hkpQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer-win32-x64-msvc": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.1.tgz",
+ "integrity": "sha512-HrVJr6+WjIXGnw3Q9u6KQcbZCtk0caVWhCdFADySvRyUxJ8PnzlaP+MhwNE8oyT8OZ6ejHBRrrgjSqDCFXGirw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@scure/base": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz",
+ "integrity": "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==",
+ "dev": true,
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@scure/bip32": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz",
+ "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "dependencies": {
+ "@noble/hashes": "~1.2.0",
+ "@noble/secp256k1": "~1.7.0",
+ "@scure/base": "~1.1.0"
+ }
+ },
+ "node_modules/@scure/bip39": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz",
+ "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "dependencies": {
+ "@noble/hashes": "~1.2.0",
+ "@scure/base": "~1.1.0"
+ }
+ },
+ "node_modules/@sentry/core": {
+ "version": "5.30.0",
+ "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz",
+ "integrity": "sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==",
+ "dev": true,
+ "dependencies": {
+ "@sentry/hub": "5.30.0",
+ "@sentry/minimal": "5.30.0",
+ "@sentry/types": "5.30.0",
+ "@sentry/utils": "5.30.0",
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@sentry/hub": {
+ "version": "5.30.0",
+ "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz",
+ "integrity": "sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==",
+ "dev": true,
+ "dependencies": {
+ "@sentry/types": "5.30.0",
+ "@sentry/utils": "5.30.0",
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@sentry/minimal": {
+ "version": "5.30.0",
+ "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz",
+ "integrity": "sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==",
+ "dev": true,
+ "dependencies": {
+ "@sentry/hub": "5.30.0",
+ "@sentry/types": "5.30.0",
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@sentry/node": {
+ "version": "5.30.0",
+ "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz",
+ "integrity": "sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==",
+ "dev": true,
+ "dependencies": {
+ "@sentry/core": "5.30.0",
+ "@sentry/hub": "5.30.0",
+ "@sentry/tracing": "5.30.0",
+ "@sentry/types": "5.30.0",
+ "@sentry/utils": "5.30.0",
+ "cookie": "^0.4.1",
+ "https-proxy-agent": "^5.0.0",
+ "lru_map": "^0.3.3",
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@sentry/tracing": {
+ "version": "5.30.0",
+ "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz",
+ "integrity": "sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==",
+ "dev": true,
+ "dependencies": {
+ "@sentry/hub": "5.30.0",
+ "@sentry/minimal": "5.30.0",
+ "@sentry/types": "5.30.0",
+ "@sentry/utils": "5.30.0",
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@sentry/types": {
+ "version": "5.30.0",
+ "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz",
+ "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@sentry/utils": {
+ "version": "5.30.0",
+ "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz",
+ "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==",
+ "dev": true,
+ "dependencies": {
+ "@sentry/types": "5.30.0",
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@types/bn.js": {
+ "version": "5.1.5",
+ "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz",
+ "integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "20.12.3",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.3.tgz",
+ "integrity": "sha512-sD+ia2ubTeWrOu+YMF+MTAB7E+O7qsMqAbMfW7DG3K1URwhZ5hN1pLlRVGbf4wDFzSfikL05M17EyorS86jShw==",
+ "dev": true,
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "node_modules/@types/pbkdf2": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.2.tgz",
+ "integrity": "sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/secp256k1": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz",
+ "integrity": "sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/adm-zip": {
+ "version": "0.4.16",
+ "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz",
+ "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.3.0"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "dev": true,
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "dev": true,
+ "dependencies": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-align": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
+ "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.1.0"
+ }
+ },
+ "node_modules/ansi-colors": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
+ "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/base-x": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz",
+ "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/blakejs": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz",
+ "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==",
+ "dev": true
+ },
+ "node_modules/bn.js": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
+ "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==",
+ "dev": true
+ },
+ "node_modules/boxen": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz",
+ "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-align": "^3.0.0",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.1.0",
+ "cli-boxes": "^2.2.1",
+ "string-width": "^4.2.2",
+ "type-fest": "^0.20.2",
+ "widest-line": "^3.1.0",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/boxen/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/boxen/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/boxen/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/boxen/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/boxen/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/boxen/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/boxen/node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/brorand": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+ "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==",
+ "dev": true
+ },
+ "node_modules/browser-stdout": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+ "dev": true
+ },
+ "node_modules/browserify-aes": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+ "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
+ "dev": true,
+ "dependencies": {
+ "buffer-xor": "^1.0.3",
+ "cipher-base": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.3",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/bs58": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
+ "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==",
+ "dev": true,
+ "dependencies": {
+ "base-x": "^3.0.2"
+ }
+ },
+ "node_modules/bs58check": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz",
+ "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==",
+ "dev": true,
+ "dependencies": {
+ "bs58": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true
+ },
+ "node_modules/buffer-xor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+ "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==",
+ "dev": true
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "dev": true,
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
+ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
+ "dev": true
+ },
+ "node_modules/cipher-base": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+ "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cli-boxes": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz",
+ "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
+ },
+ "node_modules/command-exists": {
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz",
+ "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==",
+ "dev": true
+ },
+ "node_modules/commander": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz",
+ "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==",
+ "dev": true
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/cookie": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
+ "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/create-hash": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+ "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+ "dev": true,
+ "dependencies": {
+ "cipher-base": "^1.0.1",
+ "inherits": "^2.0.1",
+ "md5.js": "^1.3.4",
+ "ripemd160": "^2.0.1",
+ "sha.js": "^2.4.0"
+ }
+ },
+ "node_modules/create-hmac": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+ "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+ "dev": true,
+ "dependencies": {
+ "cipher-base": "^1.0.3",
+ "create-hash": "^1.1.0",
+ "inherits": "^2.0.1",
+ "ripemd160": "^2.0.0",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decamelize": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
+ "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/diff": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
+ "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/elliptic": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
+ "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^4.11.9",
+ "brorand": "^1.1.0",
+ "hash.js": "^1.0.0",
+ "hmac-drbg": "^1.0.1",
+ "inherits": "^2.0.4",
+ "minimalistic-assert": "^1.0.1",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
+ "node_modules/elliptic/node_modules/bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/enquirer": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz",
+ "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-colors": "^4.1.1",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/env-paths": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+ "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
+ "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/ethereum-cryptography": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz",
+ "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==",
+ "dev": true,
+ "dependencies": {
+ "@noble/hashes": "1.2.0",
+ "@noble/secp256k1": "1.7.1",
+ "@scure/bip32": "1.1.5",
+ "@scure/bip39": "1.1.1"
+ }
+ },
+ "node_modules/ethereumjs-abi": {
+ "version": "0.6.8",
+ "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz",
+ "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^4.11.8",
+ "ethereumjs-util": "^6.0.0"
+ }
+ },
+ "node_modules/ethereumjs-abi/node_modules/bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ },
+ "node_modules/ethereumjs-util": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz",
+ "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==",
+ "dev": true,
+ "dependencies": {
+ "@types/bn.js": "^4.11.3",
+ "bn.js": "^4.11.0",
+ "create-hash": "^1.1.2",
+ "elliptic": "^6.5.2",
+ "ethereum-cryptography": "^0.1.3",
+ "ethjs-util": "0.1.6",
+ "rlp": "^2.2.3"
+ }
+ },
+ "node_modules/ethereumjs-util/node_modules/@types/bn.js": {
+ "version": "4.11.6",
+ "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz",
+ "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/ethereumjs-util/node_modules/bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ },
+ "node_modules/ethereumjs-util/node_modules/ethereum-cryptography": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz",
+ "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/pbkdf2": "^3.0.0",
+ "@types/secp256k1": "^4.0.1",
+ "blakejs": "^1.1.0",
+ "browserify-aes": "^1.2.0",
+ "bs58check": "^2.1.2",
+ "create-hash": "^1.2.0",
+ "create-hmac": "^1.1.7",
+ "hash.js": "^1.1.7",
+ "keccak": "^3.0.0",
+ "pbkdf2": "^3.0.17",
+ "randombytes": "^2.1.0",
+ "safe-buffer": "^5.1.2",
+ "scrypt-js": "^3.0.0",
+ "secp256k1": "^4.0.1",
+ "setimmediate": "^1.0.5"
+ }
+ },
+ "node_modules/ethjs-util": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz",
+ "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==",
+ "dev": true,
+ "dependencies": {
+ "is-hex-prefixed": "1.0.0",
+ "strip-hex-prefix": "1.0.0"
+ },
+ "engines": {
+ "node": ">=6.5.0",
+ "npm": ">=3"
+ }
+ },
+ "node_modules/evp_bytestokey": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+ "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+ "dev": true,
+ "dependencies": {
+ "md5.js": "^1.3.4",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/flat": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+ "dev": true,
+ "bin": {
+ "flat": "cli.js"
+ }
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.6",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
+ "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/fp-ts": {
+ "version": "1.19.3",
+ "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz",
+ "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==",
+ "dev": true
+ },
+ "node_modules/fs-extra": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
+ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=6 <7 || >=8"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true
+ },
+ "node_modules/hardhat": {
+ "version": "2.22.3",
+ "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.3.tgz",
+ "integrity": "sha512-k8JV2ECWNchD6ahkg2BR5wKVxY0OiKot7fuxiIpRK0frRqyOljcR2vKwgWSLw6YIeDcNNA4xybj7Og7NSxr2hA==",
+ "dev": true,
+ "dependencies": {
+ "@ethersproject/abi": "^5.1.2",
+ "@metamask/eth-sig-util": "^4.0.0",
+ "@nomicfoundation/edr": "^0.3.5",
+ "@nomicfoundation/ethereumjs-common": "4.0.4",
+ "@nomicfoundation/ethereumjs-tx": "5.0.4",
+ "@nomicfoundation/ethereumjs-util": "9.0.4",
+ "@nomicfoundation/solidity-analyzer": "^0.1.0",
+ "@sentry/node": "^5.18.1",
+ "@types/bn.js": "^5.1.0",
+ "@types/lru-cache": "^5.1.0",
+ "adm-zip": "^0.4.16",
+ "aggregate-error": "^3.0.0",
+ "ansi-escapes": "^4.3.0",
+ "boxen": "^5.1.2",
+ "chalk": "^2.4.2",
+ "chokidar": "^3.4.0",
+ "ci-info": "^2.0.0",
+ "debug": "^4.1.1",
+ "enquirer": "^2.3.0",
+ "env-paths": "^2.2.0",
+ "ethereum-cryptography": "^1.0.3",
+ "ethereumjs-abi": "^0.6.8",
+ "find-up": "^2.1.0",
+ "fp-ts": "1.19.3",
+ "fs-extra": "^7.0.1",
+ "glob": "7.2.0",
+ "immutable": "^4.0.0-rc.12",
+ "io-ts": "1.10.4",
+ "keccak": "^3.0.2",
+ "lodash": "^4.17.11",
+ "mnemonist": "^0.38.0",
+ "mocha": "^10.0.0",
+ "p-map": "^4.0.0",
+ "raw-body": "^2.4.1",
+ "resolve": "1.17.0",
+ "semver": "^6.3.0",
+ "solc": "0.7.3",
+ "source-map-support": "^0.5.13",
+ "stacktrace-parser": "^0.1.10",
+ "tsort": "0.0.1",
+ "undici": "^5.14.0",
+ "uuid": "^8.3.2",
+ "ws": "^7.4.6"
+ },
+ "bin": {
+ "hardhat": "internal/cli/bootstrap.js"
+ },
+ "peerDependencies": {
+ "ts-node": "*",
+ "typescript": "*"
+ },
+ "peerDependenciesMeta": {
+ "ts-node": {
+ "optional": true
+ },
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/hash-base": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
+ "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.6.0",
+ "safe-buffer": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/hash.js": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
+ "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "minimalistic-assert": "^1.0.1"
+ }
+ },
+ "node_modules/he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "dev": true,
+ "bin": {
+ "he": "bin/he"
+ }
+ },
+ "node_modules/hmac-drbg": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+ "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==",
+ "dev": true,
+ "dependencies": {
+ "hash.js": "^1.0.3",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "dev": true,
+ "dependencies": {
+ "depd": "2.0.0",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "toidentifier": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "dev": true,
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/immutable": {
+ "version": "4.3.5",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz",
+ "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==",
+ "dev": true
+ },
+ "node_modules/indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/io-ts": {
+ "version": "1.10.4",
+ "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz",
+ "integrity": "sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==",
+ "dev": true,
+ "dependencies": {
+ "fp-ts": "^1.0.0"
+ }
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-hex-prefixed": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz",
+ "integrity": "sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.5.0",
+ "npm": ">=3"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/js-sha3": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
+ "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==",
+ "dev": true
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
+ "dev": true,
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/keccak": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz",
+ "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==",
+ "dev": true,
+ "hasInstallScript": true,
+ "dependencies": {
+ "node-addon-api": "^2.0.0",
+ "node-gyp-build": "^4.2.0",
+ "readable-stream": "^3.6.0"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/klaw": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
+ "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==",
+ "dev": true,
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.9"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
+ },
+ "node_modules/log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-symbols/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/log-symbols/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/log-symbols/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/log-symbols/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/log-symbols/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/log-symbols/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/lru_map": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz",
+ "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==",
+ "dev": true
+ },
+ "node_modules/md5.js": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+ "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+ "dev": true,
+ "dependencies": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "node_modules/memorystream": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
+ "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
+ "dev": true
+ },
+ "node_modules/minimalistic-crypto-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+ "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==",
+ "dev": true
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/mnemonist": {
+ "version": "0.38.5",
+ "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz",
+ "integrity": "sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==",
+ "dev": true,
+ "dependencies": {
+ "obliterator": "^2.0.0"
+ }
+ },
+ "node_modules/mocha": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz",
+ "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-colors": "4.1.1",
+ "browser-stdout": "1.3.1",
+ "chokidar": "3.5.3",
+ "debug": "4.3.4",
+ "diff": "5.0.0",
+ "escape-string-regexp": "4.0.0",
+ "find-up": "5.0.0",
+ "glob": "8.1.0",
+ "he": "1.2.0",
+ "js-yaml": "4.1.0",
+ "log-symbols": "4.1.0",
+ "minimatch": "5.0.1",
+ "ms": "2.1.3",
+ "serialize-javascript": "6.0.0",
+ "strip-json-comments": "3.1.1",
+ "supports-color": "8.1.1",
+ "workerpool": "6.2.1",
+ "yargs": "16.2.0",
+ "yargs-parser": "20.2.4",
+ "yargs-unparser": "2.0.0"
+ },
+ "bin": {
+ "_mocha": "bin/_mocha",
+ "mocha": "bin/mocha.js"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/mocha/node_modules/ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/mocha/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/mocha/node_modules/chokidar": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/mocha/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/mocha/node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/mocha/node_modules/glob": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
+ "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/mocha/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/mocha/node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/mocha/node_modules/minimatch": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+ "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/mocha/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true
+ },
+ "node_modules/mocha/node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/mocha/node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/mocha/node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/mocha/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/node-addon-api": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz",
+ "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==",
+ "dev": true
+ },
+ "node_modules/node-gyp-build": {
+ "version": "4.8.0",
+ "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz",
+ "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==",
+ "dev": true,
+ "bin": {
+ "node-gyp-build": "bin.js",
+ "node-gyp-build-optional": "optional.js",
+ "node-gyp-build-test": "build-test.js"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/obliterator": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz",
+ "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==",
+ "dev": true
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "dev": true,
+ "dependencies": {
+ "aggregate-error": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "node_modules/pbkdf2": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz",
+ "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==",
+ "dev": true,
+ "dependencies": {
+ "create-hash": "^1.1.2",
+ "create-hmac": "^1.1.4",
+ "ripemd160": "^2.0.1",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ },
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
+ "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
+ "dev": true,
+ "dependencies": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
+ "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
+ "dev": true,
+ "dependencies": {
+ "path-parse": "^1.0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/ripemd160": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
+ "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
+ "dev": true,
+ "dependencies": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1"
+ }
+ },
+ "node_modules/rlp": {
+ "version": "2.2.7",
+ "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz",
+ "integrity": "sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^5.2.0"
+ },
+ "bin": {
+ "rlp": "bin/rlp"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "node_modules/scrypt-js": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz",
+ "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==",
+ "dev": true
+ },
+ "node_modules/secp256k1": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz",
+ "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "dependencies": {
+ "elliptic": "^6.5.4",
+ "node-addon-api": "^2.0.0",
+ "node-gyp-build": "^4.2.0"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/serialize-javascript": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+ "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
+ "dev": true,
+ "dependencies": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "node_modules/setimmediate": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+ "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
+ "dev": true
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "dev": true
+ },
+ "node_modules/sha.js": {
+ "version": "2.4.11",
+ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+ "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ },
+ "bin": {
+ "sha.js": "bin.js"
+ }
+ },
+ "node_modules/solc": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz",
+ "integrity": "sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==",
+ "dev": true,
+ "dependencies": {
+ "command-exists": "^1.2.8",
+ "commander": "3.0.2",
+ "follow-redirects": "^1.12.1",
+ "fs-extra": "^0.30.0",
+ "js-sha3": "0.8.0",
+ "memorystream": "^0.3.1",
+ "require-from-string": "^2.0.0",
+ "semver": "^5.5.0",
+ "tmp": "0.0.33"
+ },
+ "bin": {
+ "solcjs": "solcjs"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/solc/node_modules/fs-extra": {
+ "version": "0.30.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz",
+ "integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^2.1.0",
+ "klaw": "^1.0.0",
+ "path-is-absolute": "^1.0.0",
+ "rimraf": "^2.2.8"
+ }
+ },
+ "node_modules/solc/node_modules/jsonfile": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
+ "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==",
+ "dev": true,
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/solc/node_modules/semver": {
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dev": true,
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/stacktrace-parser": {
+ "version": "0.1.10",
+ "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz",
+ "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.7.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/stacktrace-parser/node_modules/type-fest": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz",
+ "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/statuses": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-hex-prefix": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz",
+ "integrity": "sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==",
+ "dev": true,
+ "dependencies": {
+ "is-hex-prefixed": "1.0.0"
+ },
+ "engines": {
+ "node": ">=6.5.0",
+ "npm": ">=3"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dev": true,
+ "dependencies": {
+ "os-tmpdir": "~1.0.2"
+ },
+ "engines": {
+ "node": ">=0.6.0"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ },
+ "node_modules/tsort": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz",
+ "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==",
+ "dev": true
+ },
+ "node_modules/tweetnacl": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
+ "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==",
+ "dev": true
+ },
+ "node_modules/tweetnacl-util": {
+ "version": "0.15.1",
+ "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz",
+ "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==",
+ "dev": true
+ },
+ "node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/undici": {
+ "version": "5.28.4",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz",
+ "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==",
+ "dev": true,
+ "dependencies": {
+ "@fastify/busboy": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=14.0"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
+ "dev": true
+ },
+ "node_modules/universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "dev": true
+ },
+ "node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "dev": true,
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/widest-line": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
+ "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/workerpool": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
+ "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
+ "dev": true
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "node_modules/ws": {
+ "version": "7.5.9",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
+ "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.3.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": "^5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs": {
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
+ "dev": true,
+ "dependencies": {
+ "cliui": "^7.0.2",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.0",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^20.2.2"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "20.2.4",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
+ "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs-unparser": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
+ "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
+ "dev": true,
+ "dependencies": {
+ "camelcase": "^6.0.0",
+ "decamelize": "^4.0.0",
+ "flat": "^5.0.2",
+ "is-plain-obj": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 00000000..abb4e645
--- /dev/null
+++ b/package.json
@@ -0,0 +1,5 @@
+{
+ "devDependencies": {
+ "hardhat": "^2.22.3"
+ }
+}
\ No newline at end of file
diff --git a/poetry.lock b/poetry.lock
index 50fbfd82..fb7df888 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,88 +1,88 @@
-# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
[[package]]
name = "aiohttp"
-version = "3.9.3"
+version = "3.9.5"
description = "Async http client/server framework (asyncio)"
optional = false
python-versions = ">=3.8"
files = [
- {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:939677b61f9d72a4fa2a042a5eee2a99a24001a67c13da113b2e30396567db54"},
- {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1f5cd333fcf7590a18334c90f8c9147c837a6ec8a178e88d90a9b96ea03194cc"},
- {file = "aiohttp-3.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82e6aa28dd46374f72093eda8bcd142f7771ee1eb9d1e223ff0fa7177a96b4a5"},
- {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f56455b0c2c7cc3b0c584815264461d07b177f903a04481dfc33e08a89f0c26b"},
- {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bca77a198bb6e69795ef2f09a5f4c12758487f83f33d63acde5f0d4919815768"},
- {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e083c285857b78ee21a96ba1eb1b5339733c3563f72980728ca2b08b53826ca5"},
- {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab40e6251c3873d86ea9b30a1ac6d7478c09277b32e14745d0d3c6e76e3c7e29"},
- {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df822ee7feaaeffb99c1a9e5e608800bd8eda6e5f18f5cfb0dc7eeb2eaa6bbec"},
- {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:acef0899fea7492145d2bbaaaec7b345c87753168589cc7faf0afec9afe9b747"},
- {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cd73265a9e5ea618014802ab01babf1940cecb90c9762d8b9e7d2cc1e1969ec6"},
- {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a78ed8a53a1221393d9637c01870248a6f4ea5b214a59a92a36f18151739452c"},
- {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6b0e029353361f1746bac2e4cc19b32f972ec03f0f943b390c4ab3371840aabf"},
- {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7cf5c9458e1e90e3c390c2639f1017a0379a99a94fdfad3a1fd966a2874bba52"},
- {file = "aiohttp-3.9.3-cp310-cp310-win32.whl", hash = "sha256:3e59c23c52765951b69ec45ddbbc9403a8761ee6f57253250c6e1536cacc758b"},
- {file = "aiohttp-3.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:055ce4f74b82551678291473f66dc9fb9048a50d8324278751926ff0ae7715e5"},
- {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b88f9386ff1ad91ace19d2a1c0225896e28815ee09fc6a8932fded8cda97c3d"},
- {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c46956ed82961e31557b6857a5ca153c67e5476972e5f7190015018760938da2"},
- {file = "aiohttp-3.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07b837ef0d2f252f96009e9b8435ec1fef68ef8b1461933253d318748ec1acdc"},
- {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad46e6f620574b3b4801c68255492e0159d1712271cc99d8bdf35f2043ec266"},
- {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ed3e046ea7b14938112ccd53d91c1539af3e6679b222f9469981e3dac7ba1ce"},
- {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:039df344b45ae0b34ac885ab5b53940b174530d4dd8a14ed8b0e2155b9dddccb"},
- {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7943c414d3a8d9235f5f15c22ace69787c140c80b718dcd57caaade95f7cd93b"},
- {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84871a243359bb42c12728f04d181a389718710129b36b6aad0fc4655a7647d4"},
- {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5eafe2c065df5401ba06821b9a054d9cb2848867f3c59801b5d07a0be3a380ae"},
- {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9d3c9b50f19704552f23b4eaea1fc082fdd82c63429a6506446cbd8737823da3"},
- {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:f033d80bc6283092613882dfe40419c6a6a1527e04fc69350e87a9df02bbc283"},
- {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2c895a656dd7e061b2fd6bb77d971cc38f2afc277229ce7dd3552de8313a483e"},
- {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1f5a71d25cd8106eab05f8704cd9167b6e5187bcdf8f090a66c6d88b634802b4"},
- {file = "aiohttp-3.9.3-cp311-cp311-win32.whl", hash = "sha256:50fca156d718f8ced687a373f9e140c1bb765ca16e3d6f4fe116e3df7c05b2c5"},
- {file = "aiohttp-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:5fe9ce6c09668063b8447f85d43b8d1c4e5d3d7e92c63173e6180b2ac5d46dd8"},
- {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:38a19bc3b686ad55804ae931012f78f7a534cce165d089a2059f658f6c91fa60"},
- {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:770d015888c2a598b377bd2f663adfd947d78c0124cfe7b959e1ef39f5b13869"},
- {file = "aiohttp-3.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee43080e75fc92bf36219926c8e6de497f9b247301bbf88c5c7593d931426679"},
- {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52df73f14ed99cee84865b95a3d9e044f226320a87af208f068ecc33e0c35b96"},
- {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc9b311743a78043b26ffaeeb9715dc360335e5517832f5a8e339f8a43581e4d"},
- {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b955ed993491f1a5da7f92e98d5dad3c1e14dc175f74517c4e610b1f2456fb11"},
- {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:504b6981675ace64c28bf4a05a508af5cde526e36492c98916127f5a02354d53"},
- {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fe5571784af92b6bc2fda8d1925cccdf24642d49546d3144948a6a1ed58ca5"},
- {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ba39e9c8627edc56544c8628cc180d88605df3892beeb2b94c9bc857774848ca"},
- {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e5e46b578c0e9db71d04c4b506a2121c0cb371dd89af17a0586ff6769d4c58c1"},
- {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:938a9653e1e0c592053f815f7028e41a3062e902095e5a7dc84617c87267ebd5"},
- {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:c3452ea726c76e92f3b9fae4b34a151981a9ec0a4847a627c43d71a15ac32aa6"},
- {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff30218887e62209942f91ac1be902cc80cddb86bf00fbc6783b7a43b2bea26f"},
- {file = "aiohttp-3.9.3-cp312-cp312-win32.whl", hash = "sha256:38f307b41e0bea3294a9a2a87833191e4bcf89bb0365e83a8be3a58b31fb7f38"},
- {file = "aiohttp-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:b791a3143681a520c0a17e26ae7465f1b6f99461a28019d1a2f425236e6eedb5"},
- {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ed621426d961df79aa3b963ac7af0d40392956ffa9be022024cd16297b30c8c"},
- {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7f46acd6a194287b7e41e87957bfe2ad1ad88318d447caf5b090012f2c5bb528"},
- {file = "aiohttp-3.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:feeb18a801aacb098220e2c3eea59a512362eb408d4afd0c242044c33ad6d542"},
- {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f734e38fd8666f53da904c52a23ce517f1b07722118d750405af7e4123933511"},
- {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b40670ec7e2156d8e57f70aec34a7216407848dfe6c693ef131ddf6e76feb672"},
- {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdd215b7b7fd4a53994f238d0f46b7ba4ac4c0adb12452beee724ddd0743ae5d"},
- {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:017a21b0df49039c8f46ca0971b3a7fdc1f56741ab1240cb90ca408049766168"},
- {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99abf0bba688259a496f966211c49a514e65afa9b3073a1fcee08856e04425b"},
- {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:648056db9a9fa565d3fa851880f99f45e3f9a771dd3ff3bb0c048ea83fb28194"},
- {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8aacb477dc26797ee089721536a292a664846489c49d3ef9725f992449eda5a8"},
- {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:522a11c934ea660ff8953eda090dcd2154d367dec1ae3c540aff9f8a5c109ab4"},
- {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5bce0dc147ca85caa5d33debc4f4d65e8e8b5c97c7f9f660f215fa74fc49a321"},
- {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b4af9f25b49a7be47c0972139e59ec0e8285c371049df1a63b6ca81fdd216a2"},
- {file = "aiohttp-3.9.3-cp38-cp38-win32.whl", hash = "sha256:298abd678033b8571995650ccee753d9458dfa0377be4dba91e4491da3f2be63"},
- {file = "aiohttp-3.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:69361bfdca5468c0488d7017b9b1e5ce769d40b46a9f4a2eed26b78619e9396c"},
- {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0fa43c32d1643f518491d9d3a730f85f5bbaedcbd7fbcae27435bb8b7a061b29"},
- {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:835a55b7ca49468aaaac0b217092dfdff370e6c215c9224c52f30daaa735c1c1"},
- {file = "aiohttp-3.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06a9b2c8837d9a94fae16c6223acc14b4dfdff216ab9b7202e07a9a09541168f"},
- {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abf151955990d23f84205286938796c55ff11bbfb4ccfada8c9c83ae6b3c89a3"},
- {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59c26c95975f26e662ca78fdf543d4eeaef70e533a672b4113dd888bd2423caa"},
- {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f95511dd5d0e05fd9728bac4096319f80615aaef4acbecb35a990afebe953b0e"},
- {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:595f105710293e76b9dc09f52e0dd896bd064a79346234b521f6b968ffdd8e58"},
- {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7c8b816c2b5af5c8a436df44ca08258fc1a13b449393a91484225fcb7545533"},
- {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f1088fa100bf46e7b398ffd9904f4808a0612e1d966b4aa43baa535d1b6341eb"},
- {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f59dfe57bb1ec82ac0698ebfcdb7bcd0e99c255bd637ff613760d5f33e7c81b3"},
- {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:361a1026c9dd4aba0109e4040e2aecf9884f5cfe1b1b1bd3d09419c205e2e53d"},
- {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:363afe77cfcbe3a36353d8ea133e904b108feea505aa4792dad6585a8192c55a"},
- {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e2c45c208c62e955e8256949eb225bd8b66a4c9b6865729a786f2aa79b72e9d"},
- {file = "aiohttp-3.9.3-cp39-cp39-win32.whl", hash = "sha256:f7217af2e14da0856e082e96ff637f14ae45c10a5714b63c77f26d8884cf1051"},
- {file = "aiohttp-3.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:27468897f628c627230dba07ec65dc8d0db566923c48f29e084ce382119802bc"},
- {file = "aiohttp-3.9.3.tar.gz", hash = "sha256:90842933e5d1ff760fae6caca4b2b3edba53ba8f4b71e95dacf2818a2aca06f7"},
+ {file = "aiohttp-3.9.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fcde4c397f673fdec23e6b05ebf8d4751314fa7c24f93334bf1f1364c1c69ac7"},
+ {file = "aiohttp-3.9.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5d6b3f1fabe465e819aed2c421a6743d8debbde79b6a8600739300630a01bf2c"},
+ {file = "aiohttp-3.9.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ae79c1bc12c34082d92bf9422764f799aee4746fd7a392db46b7fd357d4a17a"},
+ {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d3ebb9e1316ec74277d19c5f482f98cc65a73ccd5430540d6d11682cd857430"},
+ {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84dabd95154f43a2ea80deffec9cb44d2e301e38a0c9d331cc4aa0166fe28ae3"},
+ {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8a02fbeca6f63cb1f0475c799679057fc9268b77075ab7cf3f1c600e81dd46b"},
+ {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c26959ca7b75ff768e2776d8055bf9582a6267e24556bb7f7bd29e677932be72"},
+ {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:714d4e5231fed4ba2762ed489b4aec07b2b9953cf4ee31e9871caac895a839c0"},
+ {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7a6a8354f1b62e15d48e04350f13e726fa08b62c3d7b8401c0a1314f02e3558"},
+ {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c413016880e03e69d166efb5a1a95d40f83d5a3a648d16486592c49ffb76d0db"},
+ {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ff84aeb864e0fac81f676be9f4685f0527b660f1efdc40dcede3c251ef1e867f"},
+ {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ad7f2919d7dac062f24d6f5fe95d401597fbb015a25771f85e692d043c9d7832"},
+ {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:702e2c7c187c1a498a4e2b03155d52658fdd6fda882d3d7fbb891a5cf108bb10"},
+ {file = "aiohttp-3.9.5-cp310-cp310-win32.whl", hash = "sha256:67c3119f5ddc7261d47163ed86d760ddf0e625cd6246b4ed852e82159617b5fb"},
+ {file = "aiohttp-3.9.5-cp310-cp310-win_amd64.whl", hash = "sha256:471f0ef53ccedec9995287f02caf0c068732f026455f07db3f01a46e49d76bbb"},
+ {file = "aiohttp-3.9.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e0ae53e33ee7476dd3d1132f932eeb39bf6125083820049d06edcdca4381f342"},
+ {file = "aiohttp-3.9.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c088c4d70d21f8ca5c0b8b5403fe84a7bc8e024161febdd4ef04575ef35d474d"},
+ {file = "aiohttp-3.9.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:639d0042b7670222f33b0028de6b4e2fad6451462ce7df2af8aee37dcac55424"},
+ {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f26383adb94da5e7fb388d441bf09c61e5e35f455a3217bfd790c6b6bc64b2ee"},
+ {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66331d00fb28dc90aa606d9a54304af76b335ae204d1836f65797d6fe27f1ca2"},
+ {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ff550491f5492ab5ed3533e76b8567f4b37bd2995e780a1f46bca2024223233"},
+ {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f22eb3a6c1080d862befa0a89c380b4dafce29dc6cd56083f630073d102eb595"},
+ {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a81b1143d42b66ffc40a441379387076243ef7b51019204fd3ec36b9f69e77d6"},
+ {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f64fd07515dad67f24b6ea4a66ae2876c01031de91c93075b8093f07c0a2d93d"},
+ {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:93e22add827447d2e26d67c9ac0161756007f152fdc5210277d00a85f6c92323"},
+ {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:55b39c8684a46e56ef8c8d24faf02de4a2b2ac60d26cee93bc595651ff545de9"},
+ {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4715a9b778f4293b9f8ae7a0a7cef9829f02ff8d6277a39d7f40565c737d3771"},
+ {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:afc52b8d969eff14e069a710057d15ab9ac17cd4b6753042c407dcea0e40bf75"},
+ {file = "aiohttp-3.9.5-cp311-cp311-win32.whl", hash = "sha256:b3df71da99c98534be076196791adca8819761f0bf6e08e07fd7da25127150d6"},
+ {file = "aiohttp-3.9.5-cp311-cp311-win_amd64.whl", hash = "sha256:88e311d98cc0bf45b62fc46c66753a83445f5ab20038bcc1b8a1cc05666f428a"},
+ {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:c7a4b7a6cf5b6eb11e109a9755fd4fda7d57395f8c575e166d363b9fc3ec4678"},
+ {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0a158704edf0abcac8ac371fbb54044f3270bdbc93e254a82b6c82be1ef08f3c"},
+ {file = "aiohttp-3.9.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d153f652a687a8e95ad367a86a61e8d53d528b0530ef382ec5aaf533140ed00f"},
+ {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82a6a97d9771cb48ae16979c3a3a9a18b600a8505b1115cfe354dfb2054468b4"},
+ {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60cdbd56f4cad9f69c35eaac0fbbdf1f77b0ff9456cebd4902f3dd1cf096464c"},
+ {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8676e8fd73141ded15ea586de0b7cda1542960a7b9ad89b2b06428e97125d4fa"},
+ {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da00da442a0e31f1c69d26d224e1efd3a1ca5bcbf210978a2ca7426dfcae9f58"},
+ {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18f634d540dd099c262e9f887c8bbacc959847cfe5da7a0e2e1cf3f14dbf2daf"},
+ {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:320e8618eda64e19d11bdb3bd04ccc0a816c17eaecb7e4945d01deee2a22f95f"},
+ {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:2faa61a904b83142747fc6a6d7ad8fccff898c849123030f8e75d5d967fd4a81"},
+ {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:8c64a6dc3fe5db7b1b4d2b5cb84c4f677768bdc340611eca673afb7cf416ef5a"},
+ {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:393c7aba2b55559ef7ab791c94b44f7482a07bf7640d17b341b79081f5e5cd1a"},
+ {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c671dc117c2c21a1ca10c116cfcd6e3e44da7fcde37bf83b2be485ab377b25da"},
+ {file = "aiohttp-3.9.5-cp312-cp312-win32.whl", hash = "sha256:5a7ee16aab26e76add4afc45e8f8206c95d1d75540f1039b84a03c3b3800dd59"},
+ {file = "aiohttp-3.9.5-cp312-cp312-win_amd64.whl", hash = "sha256:5ca51eadbd67045396bc92a4345d1790b7301c14d1848feaac1d6a6c9289e888"},
+ {file = "aiohttp-3.9.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:694d828b5c41255e54bc2dddb51a9f5150b4eefa9886e38b52605a05d96566e8"},
+ {file = "aiohttp-3.9.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0605cc2c0088fcaae79f01c913a38611ad09ba68ff482402d3410bf59039bfb8"},
+ {file = "aiohttp-3.9.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4558e5012ee03d2638c681e156461d37b7a113fe13970d438d95d10173d25f78"},
+ {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dbc053ac75ccc63dc3a3cc547b98c7258ec35a215a92bd9f983e0aac95d3d5b"},
+ {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4109adee842b90671f1b689901b948f347325045c15f46b39797ae1bf17019de"},
+ {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6ea1a5b409a85477fd8e5ee6ad8f0e40bf2844c270955e09360418cfd09abac"},
+ {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3c2890ca8c59ee683fd09adf32321a40fe1cf164e3387799efb2acebf090c11"},
+ {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3916c8692dbd9d55c523374a3b8213e628424d19116ac4308e434dbf6d95bbdd"},
+ {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8d1964eb7617907c792ca00b341b5ec3e01ae8c280825deadbbd678447b127e1"},
+ {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d5ab8e1f6bee051a4bf6195e38a5c13e5e161cb7bad83d8854524798bd9fcd6e"},
+ {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:52c27110f3862a1afbcb2af4281fc9fdc40327fa286c4625dfee247c3ba90156"},
+ {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:7f64cbd44443e80094309875d4f9c71d0401e966d191c3d469cde4642bc2e031"},
+ {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8b4f72fbb66279624bfe83fd5eb6aea0022dad8eec62b71e7bf63ee1caadeafe"},
+ {file = "aiohttp-3.9.5-cp38-cp38-win32.whl", hash = "sha256:6380c039ec52866c06d69b5c7aad5478b24ed11696f0e72f6b807cfb261453da"},
+ {file = "aiohttp-3.9.5-cp38-cp38-win_amd64.whl", hash = "sha256:da22dab31d7180f8c3ac7c7635f3bcd53808f374f6aa333fe0b0b9e14b01f91a"},
+ {file = "aiohttp-3.9.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1732102949ff6087589408d76cd6dea656b93c896b011ecafff418c9661dc4ed"},
+ {file = "aiohttp-3.9.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c6021d296318cb6f9414b48e6a439a7f5d1f665464da507e8ff640848ee2a58a"},
+ {file = "aiohttp-3.9.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:239f975589a944eeb1bad26b8b140a59a3a320067fb3cd10b75c3092405a1372"},
+ {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b7b30258348082826d274504fbc7c849959f1989d86c29bc355107accec6cfb"},
+ {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd2adf5c87ff6d8b277814a28a535b59e20bfea40a101db6b3bdca7e9926bc24"},
+ {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9a3d838441bebcf5cf442700e3963f58b5c33f015341f9ea86dcd7d503c07e2"},
+ {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e3a1ae66e3d0c17cf65c08968a5ee3180c5a95920ec2731f53343fac9bad106"},
+ {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c69e77370cce2d6df5d12b4e12bdcca60c47ba13d1cbbc8645dd005a20b738b"},
+ {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf56238f4bbf49dab8c2dc2e6b1b68502b1e88d335bea59b3f5b9f4c001475"},
+ {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d1469f228cd9ffddd396d9948b8c9cd8022b6d1bf1e40c6f25b0fb90b4f893ed"},
+ {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:45731330e754f5811c314901cebdf19dd776a44b31927fa4b4dbecab9e457b0c"},
+ {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:3fcb4046d2904378e3aeea1df51f697b0467f2aac55d232c87ba162709478c46"},
+ {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8cf142aa6c1a751fcb364158fd710b8a9be874b81889c2bd13aa8893197455e2"},
+ {file = "aiohttp-3.9.5-cp39-cp39-win32.whl", hash = "sha256:7b179eea70833c8dee51ec42f3b4097bd6370892fa93f510f76762105568cf09"},
+ {file = "aiohttp-3.9.5-cp39-cp39-win_amd64.whl", hash = "sha256:38d80498e2e169bc61418ff36170e0aad0cd268da8b38a17c4cf29d254a8b3f1"},
+ {file = "aiohttp-3.9.5.tar.gz", hash = "sha256:edea7d15772ceeb29db4aff55e482d4bcfb6ae160ce144f2682de02f6d693551"},
]
[package.dependencies]
@@ -130,24 +130,24 @@ tz = ["backports.zoneinfo"]
[[package]]
name = "annotated-types"
-version = "0.6.0"
+version = "0.7.0"
description = "Reusable constraint types to use with typing.Annotated"
optional = false
python-versions = ">=3.8"
files = [
- {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"},
- {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"},
+ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"},
+ {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
]
[[package]]
name = "anyio"
-version = "4.3.0"
+version = "4.4.0"
description = "High level compatibility layer for multiple asynchronous event loop implementations"
optional = false
python-versions = ">=3.8"
files = [
- {file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"},
- {file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"},
+ {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"},
+ {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"},
]
[package.dependencies]
@@ -332,33 +332,33 @@ files = [
[[package]]
name = "black"
-version = "24.2.0"
+version = "24.4.2"
description = "The uncompromising code formatter."
optional = false
python-versions = ">=3.8"
files = [
- {file = "black-24.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6981eae48b3b33399c8757036c7f5d48a535b962a7c2310d19361edeef64ce29"},
- {file = "black-24.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d533d5e3259720fdbc1b37444491b024003e012c5173f7d06825a77508085430"},
- {file = "black-24.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61a0391772490ddfb8a693c067df1ef5227257e72b0e4108482b8d41b5aee13f"},
- {file = "black-24.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:992e451b04667116680cb88f63449267c13e1ad134f30087dec8527242e9862a"},
- {file = "black-24.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:163baf4ef40e6897a2a9b83890e59141cc8c2a98f2dda5080dc15c00ee1e62cd"},
- {file = "black-24.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e37c99f89929af50ffaf912454b3e3b47fd64109659026b678c091a4cd450fb2"},
- {file = "black-24.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9de21bafcba9683853f6c96c2d515e364aee631b178eaa5145fc1c61a3cc92"},
- {file = "black-24.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:9db528bccb9e8e20c08e716b3b09c6bdd64da0dd129b11e160bf082d4642ac23"},
- {file = "black-24.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d84f29eb3ee44859052073b7636533ec995bd0f64e2fb43aeceefc70090e752b"},
- {file = "black-24.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e08fb9a15c914b81dd734ddd7fb10513016e5ce7e6704bdd5e1251ceee51ac9"},
- {file = "black-24.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:810d445ae6069ce64030c78ff6127cd9cd178a9ac3361435708b907d8a04c693"},
- {file = "black-24.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ba15742a13de85e9b8f3239c8f807723991fbfae24bad92d34a2b12e81904982"},
- {file = "black-24.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7e53a8c630f71db01b28cd9602a1ada68c937cbf2c333e6ed041390d6968faf4"},
- {file = "black-24.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:93601c2deb321b4bad8f95df408e3fb3943d85012dddb6121336b8e24a0d1218"},
- {file = "black-24.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0057f800de6acc4407fe75bb147b0c2b5cbb7c3ed110d3e5999cd01184d53b0"},
- {file = "black-24.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:faf2ee02e6612577ba0181f4347bcbcf591eb122f7841ae5ba233d12c39dcb4d"},
- {file = "black-24.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:057c3dc602eaa6fdc451069bd027a1b2635028b575a6c3acfd63193ced20d9c8"},
- {file = "black-24.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:08654d0797e65f2423f850fc8e16a0ce50925f9337fb4a4a176a7aa4026e63f8"},
- {file = "black-24.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca610d29415ee1a30a3f30fab7a8f4144e9d34c89a235d81292a1edb2b55f540"},
- {file = "black-24.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:4dd76e9468d5536abd40ffbc7a247f83b2324f0c050556d9c371c2b9a9a95e31"},
- {file = "black-24.2.0-py3-none-any.whl", hash = "sha256:e8a6ae970537e67830776488bca52000eaa37fa63b9988e8c487458d9cd5ace6"},
- {file = "black-24.2.0.tar.gz", hash = "sha256:bce4f25c27c3435e4dace4815bcb2008b87e167e3bf4ee47ccdc5ce906eb4894"},
+ {file = "black-24.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce"},
+ {file = "black-24.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021"},
+ {file = "black-24.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063"},
+ {file = "black-24.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:7768a0dbf16a39aa5e9a3ded568bb545c8c2727396d063bbaf847df05b08cd96"},
+ {file = "black-24.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474"},
+ {file = "black-24.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c"},
+ {file = "black-24.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb"},
+ {file = "black-24.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1"},
+ {file = "black-24.4.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:accf49e151c8ed2c0cdc528691838afd217c50412534e876a19270fea1e28e2d"},
+ {file = "black-24.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:88c57dc656038f1ab9f92b3eb5335ee9b021412feaa46330d5eba4e51fe49b04"},
+ {file = "black-24.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be8bef99eb46d5021bf053114442914baeb3649a89dc5f3a555c88737e5e98fc"},
+ {file = "black-24.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:415e686e87dbbe6f4cd5ef0fbf764af7b89f9057b97c908742b6008cc554b9c0"},
+ {file = "black-24.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bf10f7310db693bb62692609b397e8d67257c55f949abde4c67f9cc574492cc7"},
+ {file = "black-24.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:98e123f1d5cfd42f886624d84464f7756f60ff6eab89ae845210631714f6db94"},
+ {file = "black-24.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48a85f2cb5e6799a9ef05347b476cce6c182d6c71ee36925a6c194d074336ef8"},
+ {file = "black-24.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:b1530ae42e9d6d5b670a34db49a94115a64596bc77710b1d05e9801e62ca0a7c"},
+ {file = "black-24.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:37aae07b029fa0174d39daf02748b379399b909652a806e5708199bd93899da1"},
+ {file = "black-24.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:da33a1a5e49c4122ccdfd56cd021ff1ebc4a1ec4e2d01594fef9b6f267a9e741"},
+ {file = "black-24.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e"},
+ {file = "black-24.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:b9176b9832e84308818a99a561e90aa479e73c523b3f77afd07913380ae2eab7"},
+ {file = "black-24.4.2-py3-none-any.whl", hash = "sha256:d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c"},
+ {file = "black-24.4.2.tar.gz", hash = "sha256:c872b53057f000085da66a19c55d68f6f8ddcac2642392ad3a355878406fbd4d"},
]
[package.dependencies]
@@ -376,17 +376,17 @@ uvloop = ["uvloop (>=0.15.2)"]
[[package]]
name = "boto3"
-version = "1.34.59"
+version = "1.34.116"
description = "The AWS SDK for Python"
optional = false
-python-versions = ">= 3.8"
+python-versions = ">=3.8"
files = [
- {file = "boto3-1.34.59-py3-none-any.whl", hash = "sha256:004e67b078be58d34469406f93cc8b95bc43becef4bbe44523a0b8e51f84c668"},
- {file = "boto3-1.34.59.tar.gz", hash = "sha256:162edf182e53c198137a28432a626dba103f787a8f5000ed4758b73ccd203fa0"},
+ {file = "boto3-1.34.116-py3-none-any.whl", hash = "sha256:e7f5ab2d1f1b90971a2b9369760c2c6bae49dae98c084a5c3f5c78e3968ace15"},
+ {file = "boto3-1.34.116.tar.gz", hash = "sha256:53cb8aeb405afa1cd2b25421e27a951aeb568026675dec020587861fac96ac87"},
]
[package.dependencies]
-botocore = ">=1.34.59,<1.35.0"
+botocore = ">=1.34.116,<1.35.0"
jmespath = ">=0.7.1,<2.0.0"
s3transfer = ">=0.10.0,<0.11.0"
@@ -395,22 +395,22 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
[[package]]
name = "botocore"
-version = "1.34.59"
+version = "1.34.116"
description = "Low-level, data-driven core of boto 3."
optional = false
-python-versions = ">= 3.8"
+python-versions = ">=3.8"
files = [
- {file = "botocore-1.34.59-py3-none-any.whl", hash = "sha256:4bc112dafb1679ab571117593f7656604726a3da0e5ae5bad00ea772fa40e75c"},
- {file = "botocore-1.34.59.tar.gz", hash = "sha256:24edb4d21d7c97dea0c6c4a80d36b3809b1443a30b0bd5e317d6c319dfac823f"},
+ {file = "botocore-1.34.116-py3-none-any.whl", hash = "sha256:ec4d42c816e9b2d87a2439ad277e7dda16a4a614ef6839cf66f4c1a58afa547c"},
+ {file = "botocore-1.34.116.tar.gz", hash = "sha256:269cae7ba99081519a9f87d7298e238d9e68ba94eb4f8ddfa906224c34cb8b6c"},
]
[package.dependencies]
jmespath = ">=0.7.1,<2.0.0"
python-dateutil = ">=2.1,<3.0.0"
-urllib3 = {version = ">=1.25.4,<2.1", markers = "python_version >= \"3.10\""}
+urllib3 = {version = ">=1.25.4,<2.2.0 || >2.2.0,<3", markers = "python_version >= \"3.10\""}
[package.extras]
-crt = ["awscrt (==0.19.19)"]
+crt = ["awscrt (==0.20.9)"]
[[package]]
name = "certifi"
@@ -597,6 +597,100 @@ files = [
{file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
]
+[[package]]
+name = "ckzg"
+version = "1.0.2"
+description = "Python bindings for C-KZG-4844"
+optional = false
+python-versions = "*"
+files = [
+ {file = "ckzg-1.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bdd082bc0f2a595e3546658ecbe1ff78fe65b0ab7e619a8197a62d94f46b5b46"},
+ {file = "ckzg-1.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:50ca4af4e2f1a1e8b0a7e97b3aef39dedbb0d52d90866ece424f13f8df1b5972"},
+ {file = "ckzg-1.0.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e9dc671b0a307ea65d0a216ca496c272dd3c1ed890ddc2a306da49b0d8ffc83"},
+ {file = "ckzg-1.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d95e97a0d0f7758119bb905fb5688222b1556de465035614883c42fe4a047d1f"},
+ {file = "ckzg-1.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27261672154cbd477d84d289845b0022fbdbe2ba45b7a2a2051c345fa04c8334"},
+ {file = "ckzg-1.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c16d5ee1ddbbbad0367ff970b3ec9f6d1879e9f928023beda59ae9e16ad99e4c"},
+ {file = "ckzg-1.0.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:09043738b029bdf4fdc82041b395cfc6f5b5cf63435e5d4d685d24fd14c834d3"},
+ {file = "ckzg-1.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3c0afa232d2312e3101aaddb6971b486b0038a0f9171500bc23143f5749eff55"},
+ {file = "ckzg-1.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:96e8281b6d58cf91b9559e1bd38132161d63467500838753364c68e825df2e2c"},
+ {file = "ckzg-1.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b874167de1d6de72890a2ad5bd9aa7adbddc41c3409923b59cf4ef27f83f79da"},
+ {file = "ckzg-1.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3d2ccd68b0743e20e853e31a08da490a8d38c7f12b9a0c4ee63ef5afa0dc2427"},
+ {file = "ckzg-1.0.2-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e8d534ddbe785c44cf1cd62ee32d78b4310d66dd70e42851f5468af655b81f5"},
+ {file = "ckzg-1.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c732cda00c76b326f39ae97edfc6773dd231b7c77288b38282584a7aee77c3a7"},
+ {file = "ckzg-1.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abc5a27284db479ead4c053ff086d6e222914f1b0aa08b80eabfa116dbed4f7a"},
+ {file = "ckzg-1.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e6bd5006cb3e802744309450183087a6594d50554814eee19065f7064dff7b05"},
+ {file = "ckzg-1.0.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3594470134eda7adf2813ad3f1da55ced98c8a393262f47ce3890c5afa05b23e"},
+ {file = "ckzg-1.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fea56f39e48b60c1ff6f751c47489e353d1bd95cae65c429cf5f87735d794431"},
+ {file = "ckzg-1.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:f769eb2e1056ca396462460079f6849c778f58884bb24b638ff7028dd2120b65"},
+ {file = "ckzg-1.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e3cb2f8c767aee57e88944f90848e8689ce43993b9ff21589cfb97a562208fe7"},
+ {file = "ckzg-1.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5b29889f5bc5db530f766871c0ff4133e7270ecf63aaa3ca756d3b2731980802"},
+ {file = "ckzg-1.0.2-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfcc70fb76b3d36125d646110d5001f2aa89c1c09ff5537a4550cdb7951f44d4"},
+ {file = "ckzg-1.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ca8a256cdd56d06bc5ef24caac64845240dbabca402c5a1966d519b2514b4ec"},
+ {file = "ckzg-1.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ea91b0236384f93ad1df01d530672f09e254bd8c3cf097ebf486aebb97f6c8c"},
+ {file = "ckzg-1.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:65311e72780105f239d1d66512629a9f468b7c9f2609b8567fc68963ac638ef9"},
+ {file = "ckzg-1.0.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:0d7600ce7a73ac41d348712d0c1fe5e4cb6caa329377064cfa3a6fd8fbffb410"},
+ {file = "ckzg-1.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:19893ee7bd7da8688382cb134cb9ee7bce5c38e3a9386e3ed99bb010487d2d17"},
+ {file = "ckzg-1.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:c3e1a9a72695e777497e95bb2213316a1138f82d1bb5d67b9c029a522d24908e"},
+ {file = "ckzg-1.0.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a2f59da9cb82b6a4be615f2561a255731eededa7ecd6ba4b2f2dedfc918ef137"},
+ {file = "ckzg-1.0.2-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c915e1f2ef51657c3255d8b1e2aea6e0b93348ae316b2b79eaadfb17ad8f514e"},
+ {file = "ckzg-1.0.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcc0d2031fcabc4be37e9e602c926ef9347238d2f58c1b07e0c147f60b9e760b"},
+ {file = "ckzg-1.0.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cdaad2745425d7708e76e8e56a52fdaf5c5cc1cfefd5129d24ff8dbe06a012d"},
+ {file = "ckzg-1.0.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:1ec775649daade1b93041aac9c1660c2ad9828b57ccd2eeb5a3074d8f05e544a"},
+ {file = "ckzg-1.0.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:02f9cc3e38b3702ec5895a1ebf927fd02b8f5c2f93c7cb9e438581b5b74472c8"},
+ {file = "ckzg-1.0.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:0e816af31951b5e94e6bc069f21fe783427c190526e0437e16c4488a34ddcacc"},
+ {file = "ckzg-1.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:651ba33ee2d7fefff14ca519a72996b733402f8b043fbfef12d5fe2a442d86d8"},
+ {file = "ckzg-1.0.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:489763ad92e2175fb6ab455411f03ec104c630470d483e11578bf2e00608f283"},
+ {file = "ckzg-1.0.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:69e1376284e9a5094d7c4d3e552202d6b32a67c5acc461b0b35718d8ec5c7363"},
+ {file = "ckzg-1.0.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb9d0b09ca1bdb5955b626d6645f811424ae0fcab47699a1a938a3ce0438c25f"},
+ {file = "ckzg-1.0.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d87a121ace8feb6c9386f247e7e36ef55e584fc8a6b1bc2c60757a59c1efe364"},
+ {file = "ckzg-1.0.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:97c27153fab853f017fed159333b27beeb2e0da834c92c9ecdc26d0e5c3983b3"},
+ {file = "ckzg-1.0.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b26799907257c39471cb3665f66f7630797140131606085c2c94a7094ab6ddf2"},
+ {file = "ckzg-1.0.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:283a40c625222560fda3dcb912b666f7d50f9502587b73c4358979f519f1c961"},
+ {file = "ckzg-1.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:5f029822d27c52b9c3dbe5706408b099da779f10929be0422a09a34aa026a872"},
+ {file = "ckzg-1.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:edaea8fb50b01c6c19768d9305ad365639a8cd804754277d5108dcae4808f00b"},
+ {file = "ckzg-1.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:27be65c88d5d773a30e6f198719cefede7e25cad807384c3d65a09c11616fc9d"},
+ {file = "ckzg-1.0.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9ac729c5c6f3d2c030c0bc8c9e10edc253e36f002cfe227292035009965d349"},
+ {file = "ckzg-1.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1528bc2b95aac6d184a90b023602c40d7b11b577235848c1b5593c00cf51d37"},
+ {file = "ckzg-1.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:071dc7fc179316ce1bfabaa056156e4e84f312c4560ab7b9529a3b9a84019df3"},
+ {file = "ckzg-1.0.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:895044069de7010be6c7ee703f03fd7548267a0823cf60b9dd26ec50267dd9e8"},
+ {file = "ckzg-1.0.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ed8c99cd3d9af596470e0481fd58931007288951719bad026f0dd486dd0ec11"},
+ {file = "ckzg-1.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:74d87eafe561d4bfb544a4f3419d26c56ad7de00f39789ef0fdb09515544d12e"},
+ {file = "ckzg-1.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:54d71e5ca416bd51c543f9f51e426e6792f8a0280b83aef92faad1b826f401ea"},
+ {file = "ckzg-1.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:da2d9988781a09a4577ee7ea8f51fe4a94b4422789a523164f5ba3118566ad41"},
+ {file = "ckzg-1.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d9e030af7d6acdcb356fddfb095048bc8e880fe4cd70ff2206c64f33bf384a0d"},
+ {file = "ckzg-1.0.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:145ae31c3d499d1950567bd636dc5b24292b600296b9deb5523bc20d8f7b51c3"},
+ {file = "ckzg-1.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d81e68e84d80084da298471ad5eaddfcc1cf73545cb24e9453550c8186870982"},
+ {file = "ckzg-1.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c67064bbbeba1a6892c9c80b3d0c2a540ff48a5ca5356fdb2a8d998b264e43e6"},
+ {file = "ckzg-1.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:99694917eb6decefc0d330d9887a89ea770824b2fa76eb830bab5fe57ea5c20c"},
+ {file = "ckzg-1.0.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:fca227ce0ce3427254a113fdb3aed5ecd99c1fc670cb0c60cc8a2154793678e4"},
+ {file = "ckzg-1.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a66a690d3d1801085d11de6825df47a99b465ff32dbe90be4a3c9f43c577da96"},
+ {file = "ckzg-1.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:272adfe471380d10e4a0e1639d877e504555079a60233dd82249c799b15be81e"},
+ {file = "ckzg-1.0.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f37be0054ebb4b8ac6e6d5267290b239b09e7ddc611776051b4c3c4032d161ba"},
+ {file = "ckzg-1.0.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:611c03a170f0f746180eeb0cc28cdc6f954561b8eb9013605a046de86520ee6b"},
+ {file = "ckzg-1.0.2-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:75b2f0ab341f3c33702ce64e1c101116c7462a25686d0b1a0193ca654ad4f96e"},
+ {file = "ckzg-1.0.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab29fc61fbd32096b82b02e6b18ae0d7423048d3540b7b90805b16ae10bdb769"},
+ {file = "ckzg-1.0.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e43741e7453262aa3ba1754623d7864250b33751bd850dd548e3ed6bd1911093"},
+ {file = "ckzg-1.0.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:155eacc237cb28c9eafda1c47a89e6e4550f1c2e711f2eee21e0bb2f4df75546"},
+ {file = "ckzg-1.0.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d31d7fbe396a51f43375e38c31bc3a96c7996882582f95f3fcfd54acfa7b3ce6"},
+ {file = "ckzg-1.0.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9d3d049186c9966e9140de39a9979d7adcfe22f8b02d2852c94d3c363235cc18"},
+ {file = "ckzg-1.0.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88728fbd410d61bd5d655ac50b842714c38bc34ff717f73592132d28911fc88e"},
+ {file = "ckzg-1.0.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:052d302058d72431acc9dd4a9c76854c8dfce10c698deef5252884e32a1ac7bf"},
+ {file = "ckzg-1.0.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:633110a9431231664be2ad32baf10971547f18289d33967654581b9ae9c94a7e"},
+ {file = "ckzg-1.0.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f439c9e5297ae29a700f6d55de1525e2e295dbbb7366f0974c8702fca9e536b9"},
+ {file = "ckzg-1.0.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:94f7eb080c00c0ccbd4fafad69f0b35b624a6a229a28e11d365b60b58a072832"},
+ {file = "ckzg-1.0.2-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f876783ec654b7b9525503c2a0a1b086e5d4f52ff65cac7e8747769b0c2e5468"},
+ {file = "ckzg-1.0.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7e039800e50592580171830e788ef4a1d6bb54300d074ae9f9119e92aefc568"},
+ {file = "ckzg-1.0.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13a8cccf0070a29bc01493179db2e61220ee1a6cb17f8ea41c68a2f043ace87f"},
+ {file = "ckzg-1.0.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4f86cef801d7b0838e17b6ee2f2c9e747447d91ad1220a701baccdf7ef11a3c8"},
+ {file = "ckzg-1.0.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2433a89af4158beddebbdd66fae95b34d40f2467bee8dc40df0333de5e616b5f"},
+ {file = "ckzg-1.0.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c49d5dc0918ad912777720035f9820bdbb6c7e7d1898e12506d44ab3c938d525"},
+ {file = "ckzg-1.0.2-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:331d49bc72430a3f85ea6ecb55a0d0d65f66a21d61af5783b465906a741366d5"},
+ {file = "ckzg-1.0.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86627bc33bc63b8de869d7d5bfa9868619a4f3e4e7082103935c52f56c66b5"},
+ {file = "ckzg-1.0.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab6a2ba2706b5eaa1ce6bc7c4e72970bf9587e2e0e482e5fb4df1996bccb7a40"},
+ {file = "ckzg-1.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:8bca5e7c38d913fabc24ad09545f78ba23cfc13e1ac8250644231729ca908549"},
+ {file = "ckzg-1.0.2.tar.gz", hash = "sha256:4295acc380f8d42ebea4a4a0a68c424a322bb335a33bad05c72ead8cbb28d118"},
+]
+
[[package]]
name = "click"
version = "8.1.7"
@@ -680,63 +774,63 @@ files = [
[[package]]
name = "coverage"
-version = "7.4.3"
+version = "7.5.3"
description = "Code coverage measurement for Python"
optional = false
python-versions = ">=3.8"
files = [
- {file = "coverage-7.4.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8580b827d4746d47294c0e0b92854c85a92c2227927433998f0d3320ae8a71b6"},
- {file = "coverage-7.4.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:718187eeb9849fc6cc23e0d9b092bc2348821c5e1a901c9f8975df0bc785bfd4"},
- {file = "coverage-7.4.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:767b35c3a246bcb55b8044fd3a43b8cd553dd1f9f2c1eeb87a302b1f8daa0524"},
- {file = "coverage-7.4.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae7f19afe0cce50039e2c782bff379c7e347cba335429678450b8fe81c4ef96d"},
- {file = "coverage-7.4.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba3a8aaed13770e970b3df46980cb068d1c24af1a1968b7818b69af8c4347efb"},
- {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ee866acc0861caebb4f2ab79f0b94dbfbdbfadc19f82e6e9c93930f74e11d7a0"},
- {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:506edb1dd49e13a2d4cac6a5173317b82a23c9d6e8df63efb4f0380de0fbccbc"},
- {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd6545d97c98a192c5ac995d21c894b581f1fd14cf389be90724d21808b657e2"},
- {file = "coverage-7.4.3-cp310-cp310-win32.whl", hash = "sha256:f6a09b360d67e589236a44f0c39218a8efba2593b6abdccc300a8862cffc2f94"},
- {file = "coverage-7.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:18d90523ce7553dd0b7e23cbb28865db23cddfd683a38fb224115f7826de78d0"},
- {file = "coverage-7.4.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cbbe5e739d45a52f3200a771c6d2c7acf89eb2524890a4a3aa1a7fa0695d2a47"},
- {file = "coverage-7.4.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:489763b2d037b164846ebac0cbd368b8a4ca56385c4090807ff9fad817de4113"},
- {file = "coverage-7.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:451f433ad901b3bb00184d83fd83d135fb682d780b38af7944c9faeecb1e0bfe"},
- {file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fcc66e222cf4c719fe7722a403888b1f5e1682d1679bd780e2b26c18bb648cdc"},
- {file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3ec74cfef2d985e145baae90d9b1b32f85e1741b04cd967aaf9cfa84c1334f3"},
- {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:abbbd8093c5229c72d4c2926afaee0e6e3140de69d5dcd918b2921f2f0c8baba"},
- {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:35eb581efdacf7b7422af677b92170da4ef34500467381e805944a3201df2079"},
- {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8249b1c7334be8f8c3abcaaa996e1e4927b0e5a23b65f5bf6cfe3180d8ca7840"},
- {file = "coverage-7.4.3-cp311-cp311-win32.whl", hash = "sha256:cf30900aa1ba595312ae41978b95e256e419d8a823af79ce670835409fc02ad3"},
- {file = "coverage-7.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:18c7320695c949de11a351742ee001849912fd57e62a706d83dfc1581897fa2e"},
- {file = "coverage-7.4.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b51bfc348925e92a9bd9b2e48dad13431b57011fd1038f08316e6bf1df107d10"},
- {file = "coverage-7.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d6cdecaedea1ea9e033d8adf6a0ab11107b49571bbb9737175444cea6eb72328"},
- {file = "coverage-7.4.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b2eccb883368f9e972e216c7b4c7c06cabda925b5f06dde0650281cb7666a30"},
- {file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c00cdc8fa4e50e1cc1f941a7f2e3e0f26cb2a1233c9696f26963ff58445bac7"},
- {file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9a4a8dd3dcf4cbd3165737358e4d7dfbd9d59902ad11e3b15eebb6393b0446e"},
- {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:062b0a75d9261e2f9c6d071753f7eef0fc9caf3a2c82d36d76667ba7b6470003"},
- {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ebe7c9e67a2d15fa97b77ea6571ce5e1e1f6b0db71d1d5e96f8d2bf134303c1d"},
- {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c0a120238dd71c68484f02562f6d446d736adcc6ca0993712289b102705a9a3a"},
- {file = "coverage-7.4.3-cp312-cp312-win32.whl", hash = "sha256:37389611ba54fd6d278fde86eb2c013c8e50232e38f5c68235d09d0a3f8aa352"},
- {file = "coverage-7.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:d25b937a5d9ffa857d41be042b4238dd61db888533b53bc76dc082cb5a15e914"},
- {file = "coverage-7.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:28ca2098939eabab044ad68850aac8f8db6bf0b29bc7f2887d05889b17346454"},
- {file = "coverage-7.4.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:280459f0a03cecbe8800786cdc23067a8fc64c0bd51dc614008d9c36e1659d7e"},
- {file = "coverage-7.4.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c0cdedd3500e0511eac1517bf560149764b7d8e65cb800d8bf1c63ebf39edd2"},
- {file = "coverage-7.4.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a9babb9466fe1da12417a4aed923e90124a534736de6201794a3aea9d98484e"},
- {file = "coverage-7.4.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dec9de46a33cf2dd87a5254af095a409ea3bf952d85ad339751e7de6d962cde6"},
- {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:16bae383a9cc5abab9bb05c10a3e5a52e0a788325dc9ba8499e821885928968c"},
- {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2c854ce44e1ee31bda4e318af1dbcfc929026d12c5ed030095ad98197eeeaed0"},
- {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ce8c50520f57ec57aa21a63ea4f325c7b657386b3f02ccaedeccf9ebe27686e1"},
- {file = "coverage-7.4.3-cp38-cp38-win32.whl", hash = "sha256:708a3369dcf055c00ddeeaa2b20f0dd1ce664eeabde6623e516c5228b753654f"},
- {file = "coverage-7.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:1bf25fbca0c8d121a3e92a2a0555c7e5bc981aee5c3fdaf4bb7809f410f696b9"},
- {file = "coverage-7.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3b253094dbe1b431d3a4ac2f053b6d7ede2664ac559705a704f621742e034f1f"},
- {file = "coverage-7.4.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77fbfc5720cceac9c200054b9fab50cb2a7d79660609200ab83f5db96162d20c"},
- {file = "coverage-7.4.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6679060424faa9c11808598504c3ab472de4531c571ab2befa32f4971835788e"},
- {file = "coverage-7.4.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4af154d617c875b52651dd8dd17a31270c495082f3d55f6128e7629658d63765"},
- {file = "coverage-7.4.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8640f1fde5e1b8e3439fe482cdc2b0bb6c329f4bb161927c28d2e8879c6029ee"},
- {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:69b9f6f66c0af29642e73a520b6fed25ff9fd69a25975ebe6acb297234eda501"},
- {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0842571634f39016a6c03e9d4aba502be652a6e4455fadb73cd3a3a49173e38f"},
- {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a78ed23b08e8ab524551f52953a8a05d61c3a760781762aac49f8de6eede8c45"},
- {file = "coverage-7.4.3-cp39-cp39-win32.whl", hash = "sha256:c0524de3ff096e15fcbfe8f056fdb4ea0bf497d584454f344d59fce069d3e6e9"},
- {file = "coverage-7.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:0209a6369ccce576b43bb227dc8322d8ef9e323d089c6f3f26a597b09cb4d2aa"},
- {file = "coverage-7.4.3-pp38.pp39.pp310-none-any.whl", hash = "sha256:7cbde573904625509a3f37b6fecea974e363460b556a627c60dc2f47e2fffa51"},
- {file = "coverage-7.4.3.tar.gz", hash = "sha256:276f6077a5c61447a48d133ed13e759c09e62aff0dc84274a68dc18660104d52"},
+ {file = "coverage-7.5.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a6519d917abb15e12380406d721e37613e2a67d166f9fb7e5a8ce0375744cd45"},
+ {file = "coverage-7.5.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:aea7da970f1feccf48be7335f8b2ca64baf9b589d79e05b9397a06696ce1a1ec"},
+ {file = "coverage-7.5.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:923b7b1c717bd0f0f92d862d1ff51d9b2b55dbbd133e05680204465f454bb286"},
+ {file = "coverage-7.5.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62bda40da1e68898186f274f832ef3e759ce929da9a9fd9fcf265956de269dbc"},
+ {file = "coverage-7.5.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8b7339180d00de83e930358223c617cc343dd08e1aa5ec7b06c3a121aec4e1d"},
+ {file = "coverage-7.5.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:25a5caf742c6195e08002d3b6c2dd6947e50efc5fc2c2205f61ecb47592d2d83"},
+ {file = "coverage-7.5.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:05ac5f60faa0c704c0f7e6a5cbfd6f02101ed05e0aee4d2822637a9e672c998d"},
+ {file = "coverage-7.5.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:239a4e75e09c2b12ea478d28815acf83334d32e722e7433471fbf641c606344c"},
+ {file = "coverage-7.5.3-cp310-cp310-win32.whl", hash = "sha256:a5812840d1d00eafae6585aba38021f90a705a25b8216ec7f66aebe5b619fb84"},
+ {file = "coverage-7.5.3-cp310-cp310-win_amd64.whl", hash = "sha256:33ca90a0eb29225f195e30684ba4a6db05dbef03c2ccd50b9077714c48153cac"},
+ {file = "coverage-7.5.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f81bc26d609bf0fbc622c7122ba6307993c83c795d2d6f6f6fd8c000a770d974"},
+ {file = "coverage-7.5.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7cec2af81f9e7569280822be68bd57e51b86d42e59ea30d10ebdbb22d2cb7232"},
+ {file = "coverage-7.5.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55f689f846661e3f26efa535071775d0483388a1ccfab899df72924805e9e7cd"},
+ {file = "coverage-7.5.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50084d3516aa263791198913a17354bd1dc627d3c1639209640b9cac3fef5807"},
+ {file = "coverage-7.5.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:341dd8f61c26337c37988345ca5c8ccabeff33093a26953a1ac72e7d0103c4fb"},
+ {file = "coverage-7.5.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ab0b028165eea880af12f66086694768f2c3139b2c31ad5e032c8edbafca6ffc"},
+ {file = "coverage-7.5.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5bc5a8c87714b0c67cfeb4c7caa82b2d71e8864d1a46aa990b5588fa953673b8"},
+ {file = "coverage-7.5.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:38a3b98dae8a7c9057bd91fbf3415c05e700a5114c5f1b5b0ea5f8f429ba6614"},
+ {file = "coverage-7.5.3-cp311-cp311-win32.whl", hash = "sha256:fcf7d1d6f5da887ca04302db8e0e0cf56ce9a5e05f202720e49b3e8157ddb9a9"},
+ {file = "coverage-7.5.3-cp311-cp311-win_amd64.whl", hash = "sha256:8c836309931839cca658a78a888dab9676b5c988d0dd34ca247f5f3e679f4e7a"},
+ {file = "coverage-7.5.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:296a7d9bbc598e8744c00f7a6cecf1da9b30ae9ad51c566291ff1314e6cbbed8"},
+ {file = "coverage-7.5.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:34d6d21d8795a97b14d503dcaf74226ae51eb1f2bd41015d3ef332a24d0a17b3"},
+ {file = "coverage-7.5.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e317953bb4c074c06c798a11dbdd2cf9979dbcaa8ccc0fa4701d80042d4ebf1"},
+ {file = "coverage-7.5.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:705f3d7c2b098c40f5b81790a5fedb274113373d4d1a69e65f8b68b0cc26f6db"},
+ {file = "coverage-7.5.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1196e13c45e327d6cd0b6e471530a1882f1017eb83c6229fc613cd1a11b53cd"},
+ {file = "coverage-7.5.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:015eddc5ccd5364dcb902eaecf9515636806fa1e0d5bef5769d06d0f31b54523"},
+ {file = "coverage-7.5.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:fd27d8b49e574e50caa65196d908f80e4dff64d7e592d0c59788b45aad7e8b35"},
+ {file = "coverage-7.5.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:33fc65740267222fc02975c061eb7167185fef4cc8f2770267ee8bf7d6a42f84"},
+ {file = "coverage-7.5.3-cp312-cp312-win32.whl", hash = "sha256:7b2a19e13dfb5c8e145c7a6ea959485ee8e2204699903c88c7d25283584bfc08"},
+ {file = "coverage-7.5.3-cp312-cp312-win_amd64.whl", hash = "sha256:0bbddc54bbacfc09b3edaec644d4ac90c08ee8ed4844b0f86227dcda2d428fcb"},
+ {file = "coverage-7.5.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f78300789a708ac1f17e134593f577407d52d0417305435b134805c4fb135adb"},
+ {file = "coverage-7.5.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b368e1aee1b9b75757942d44d7598dcd22a9dbb126affcbba82d15917f0cc155"},
+ {file = "coverage-7.5.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f836c174c3a7f639bded48ec913f348c4761cbf49de4a20a956d3431a7c9cb24"},
+ {file = "coverage-7.5.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:244f509f126dc71369393ce5fea17c0592c40ee44e607b6d855e9c4ac57aac98"},
+ {file = "coverage-7.5.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4c2872b3c91f9baa836147ca33650dc5c172e9273c808c3c3199c75490e709d"},
+ {file = "coverage-7.5.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dd4b3355b01273a56b20c219e74e7549e14370b31a4ffe42706a8cda91f19f6d"},
+ {file = "coverage-7.5.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f542287b1489c7a860d43a7d8883e27ca62ab84ca53c965d11dac1d3a1fab7ce"},
+ {file = "coverage-7.5.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:75e3f4e86804023e991096b29e147e635f5e2568f77883a1e6eed74512659ab0"},
+ {file = "coverage-7.5.3-cp38-cp38-win32.whl", hash = "sha256:c59d2ad092dc0551d9f79d9d44d005c945ba95832a6798f98f9216ede3d5f485"},
+ {file = "coverage-7.5.3-cp38-cp38-win_amd64.whl", hash = "sha256:fa21a04112c59ad54f69d80e376f7f9d0f5f9123ab87ecd18fbb9ec3a2beed56"},
+ {file = "coverage-7.5.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f5102a92855d518b0996eb197772f5ac2a527c0ec617124ad5242a3af5e25f85"},
+ {file = "coverage-7.5.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d1da0a2e3b37b745a2b2a678a4c796462cf753aebf94edcc87dcc6b8641eae31"},
+ {file = "coverage-7.5.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8383a6c8cefba1b7cecc0149415046b6fc38836295bc4c84e820872eb5478b3d"},
+ {file = "coverage-7.5.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9aad68c3f2566dfae84bf46295a79e79d904e1c21ccfc66de88cd446f8686341"},
+ {file = "coverage-7.5.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e079c9ec772fedbade9d7ebc36202a1d9ef7291bc9b3a024ca395c4d52853d7"},
+ {file = "coverage-7.5.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bde997cac85fcac227b27d4fb2c7608a2c5f6558469b0eb704c5726ae49e1c52"},
+ {file = "coverage-7.5.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:990fb20b32990b2ce2c5f974c3e738c9358b2735bc05075d50a6f36721b8f303"},
+ {file = "coverage-7.5.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3d5a67f0da401e105753d474369ab034c7bae51a4c31c77d94030d59e41df5bd"},
+ {file = "coverage-7.5.3-cp39-cp39-win32.whl", hash = "sha256:e08c470c2eb01977d221fd87495b44867a56d4d594f43739a8028f8646a51e0d"},
+ {file = "coverage-7.5.3-cp39-cp39-win_amd64.whl", hash = "sha256:1d2a830ade66d3563bb61d1e3c77c8def97b30ed91e166c67d0632c018f380f0"},
+ {file = "coverage-7.5.3-pp38.pp39.pp310-none-any.whl", hash = "sha256:3538d8fb1ee9bdd2e2692b3b18c22bb1c19ffbefd06880f5ac496e42d7bb3884"},
+ {file = "coverage-7.5.3.tar.gz", hash = "sha256:04aefca5190d1dc7a53a4c1a5a7f8568811306d7a8ee231c42fb69215571944f"},
]
[package.extras]
@@ -872,21 +966,56 @@ files = [
{file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"},
]
+[[package]]
+name = "dnspython"
+version = "2.6.1"
+description = "DNS toolkit"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "dnspython-2.6.1-py3-none-any.whl", hash = "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50"},
+ {file = "dnspython-2.6.1.tar.gz", hash = "sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc"},
+]
+
+[package.extras]
+dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "sphinx (>=7.2.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"]
+dnssec = ["cryptography (>=41)"]
+doh = ["h2 (>=4.1.0)", "httpcore (>=1.0.0)", "httpx (>=0.26.0)"]
+doq = ["aioquic (>=0.9.25)"]
+idna = ["idna (>=3.6)"]
+trio = ["trio (>=0.23)"]
+wmi = ["wmi (>=1.5.1)"]
+
+[[package]]
+name = "email-validator"
+version = "2.1.1"
+description = "A robust email address syntax and deliverability validation library."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "email_validator-2.1.1-py3-none-any.whl", hash = "sha256:97d882d174e2a65732fb43bfce81a3a834cbc1bde8bf419e30ef5ea976370a05"},
+ {file = "email_validator-2.1.1.tar.gz", hash = "sha256:200a70680ba08904be6d1eef729205cc0d687634399a5924d842533efb824b84"},
+]
+
+[package.dependencies]
+dnspython = ">=2.0.0"
+idna = ">=2.0.0"
+
[[package]]
name = "eth-abi"
-version = "5.0.1"
+version = "5.1.0"
description = "eth_abi: Python utilities for working with Ethereum ABI definitions, especially encoding and decoding"
optional = false
-python-versions = ">=3.8, <4"
+python-versions = "<4,>=3.8"
files = [
- {file = "eth_abi-5.0.1-py3-none-any.whl", hash = "sha256:521960d8b4beee514958e1774951dc6b48176aa274e3bd8b166f6921453047ef"},
- {file = "eth_abi-5.0.1.tar.gz", hash = "sha256:e9425110c6120c585c9f0db2e8a33d76c4b886b148a65e68fc0035d3917a3b9c"},
+ {file = "eth_abi-5.1.0-py3-none-any.whl", hash = "sha256:84cac2626a7db8b7d9ebe62b0fdca676ab1014cc7f777189e3c0cd721a4c16d8"},
+ {file = "eth_abi-5.1.0.tar.gz", hash = "sha256:33ddd756206e90f7ddff1330cc8cac4aa411a824fe779314a0a52abea2c8fc14"},
]
[package.dependencies]
eth-typing = ">=3.0.0"
eth-utils = ">=2.0.0"
-parsimonious = ">=0.9.0,<0.10.0"
+parsimonious = ">=0.10.0,<0.11.0"
[package.extras]
dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-hash[pycryptodome]", "hypothesis (>=4.18.2,<5.0.0)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-timeout (>=2.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"]
@@ -896,28 +1025,30 @@ tools = ["hypothesis (>=4.18.2,<5.0.0)"]
[[package]]
name = "eth-account"
-version = "0.11.0"
+version = "0.13.0"
description = "eth-account: Sign Ethereum transactions and messages with local private keys"
optional = false
-python-versions = ">=3.8, <4"
+python-versions = "<4,>=3.8"
files = [
- {file = "eth-account-0.11.0.tar.gz", hash = "sha256:2ffc7a0c7538053a06a7d11495c16c7ad9897dd42be0f64ca7551e9f6e0738c3"},
- {file = "eth_account-0.11.0-py3-none-any.whl", hash = "sha256:76dd261ea096ee09e51455b0a4c99f22185516fdc062f63df0817c28f605e430"},
+ {file = "eth_account-0.13.0-py3-none-any.whl", hash = "sha256:84d27664038c68e6bee28fa5de803c3b629dc5d97cd61d12e5f442c561a5b8af"},
+ {file = "eth_account-0.13.0.tar.gz", hash = "sha256:ccea4383d9d37b46e17c977b0a5ea397cef1ac1ad3330431ae4b0c10b62d4fcd"},
]
[package.dependencies]
bitarray = ">=2.4.0"
+ckzg = ">=0.4.3"
eth-abi = ">=4.0.0-b.2"
eth-keyfile = ">=0.6.0"
eth-keys = ">=0.4.0"
-eth-rlp = ">=0.3.0"
+eth-rlp = ">=2.1.0"
eth-utils = ">=2.0.0"
-hexbytes = ">=0.1.0,<0.4.0"
+hexbytes = ">=1.2.0"
+pydantic = ">=2.0.0"
rlp = ">=1.0.0"
[package.extras]
-dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "coverage", "hypothesis (>=4.18.0,<5)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"]
-docs = ["sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"]
+dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "coverage", "hypothesis (>=4.18.0,<5)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"]
+docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"]
test = ["coverage", "hypothesis (>=4.18.0,<5)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"]
[[package]]
@@ -943,13 +1074,13 @@ test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"]
[[package]]
name = "eth-keyfile"
-version = "0.7.0"
+version = "0.8.1"
description = "eth-keyfile: A library for handling the encrypted keyfiles used to store ethereum private keys"
optional = false
-python-versions = ">=3.8, <4"
+python-versions = "<4,>=3.8"
files = [
- {file = "eth-keyfile-0.7.0.tar.gz", hash = "sha256:6bdb8110c3a50439deb68a04c93c9d5ddd5402353bfae1bf4cfca1d6dff14fcf"},
- {file = "eth_keyfile-0.7.0-py3-none-any.whl", hash = "sha256:6a89b231a2fe250c3a8f924f2695bb9cce33ddd0d6f7ebbcdacd183d7f83d537"},
+ {file = "eth_keyfile-0.8.1-py3-none-any.whl", hash = "sha256:65387378b82fe7e86d7cb9f8d98e6d639142661b2f6f490629da09fddbef6d64"},
+ {file = "eth_keyfile-0.8.1.tar.gz", hash = "sha256:9708bc31f386b52cca0969238ff35b1ac72bd7a7186f2a84b86110d3c973bec1"},
]
[package.dependencies]
@@ -964,13 +1095,13 @@ test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"]
[[package]]
name = "eth-keys"
-version = "0.5.0"
+version = "0.5.1"
description = "eth-keys: Common API for Ethereum key operations"
optional = false
-python-versions = ">=3.8, <4"
+python-versions = "<4,>=3.8"
files = [
- {file = "eth-keys-0.5.0.tar.gz", hash = "sha256:a0abccb83f3d84322591a2c047a1e3aa52ea86b185fa3e82ce311d120ca2791e"},
- {file = "eth_keys-0.5.0-py3-none-any.whl", hash = "sha256:b2bed3ff3bcede68cc0cd4458c7147baaeaac1211a1efdb6ca019f9d3d989f2b"},
+ {file = "eth_keys-0.5.1-py3-none-any.whl", hash = "sha256:ad13d920a2217a49bed3a1a7f54fb0980f53caf86d3bbab2139fd3330a17b97e"},
+ {file = "eth_keys-0.5.1.tar.gz", hash = "sha256:2b587e4bbb9ac2195215a7ab0c0fb16042b17d4ec50240ed670bbb8f53da7a48"},
]
[package.dependencies]
@@ -979,26 +1110,25 @@ eth-utils = ">=2"
[package.extras]
coincurve = ["coincurve (>=12.0.0)"]
-dev = ["asn1tools (>=0.146.2)", "build (>=0.9.0)", "bumpversion (>=0.5.3)", "coincurve (>=12.0.0)", "eth-hash[pysha3]", "factory-boy (>=3.0.1)", "hypothesis (>=5.10.3,<6)", "ipython", "pre-commit (>=3.4.0)", "pyasn1 (>=0.4.5)", "pytest (>=7.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"]
+dev = ["asn1tools (>=0.146.2)", "build (>=0.9.0)", "bumpversion (>=0.5.3)", "coincurve (>=12.0.0)", "eth-hash[pysha3]", "factory-boy (>=3.0.1)", "hypothesis (>=5.10.3)", "ipython", "pre-commit (>=3.4.0)", "pyasn1 (>=0.4.5)", "pytest (>=7.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"]
docs = ["towncrier (>=21,<22)"]
-test = ["asn1tools (>=0.146.2)", "eth-hash[pysha3]", "factory-boy (>=3.0.1)", "hypothesis (>=5.10.3,<6)", "pyasn1 (>=0.4.5)", "pytest (>=7.0.0)"]
+test = ["asn1tools (>=0.146.2)", "eth-hash[pysha3]", "factory-boy (>=3.0.1)", "hypothesis (>=5.10.3)", "pyasn1 (>=0.4.5)", "pytest (>=7.0.0)"]
[[package]]
name = "eth-rlp"
-version = "1.0.1"
+version = "2.1.0"
description = "eth-rlp: RLP definitions for common Ethereum objects in Python"
optional = false
python-versions = ">=3.8, <4"
files = [
- {file = "eth-rlp-1.0.1.tar.gz", hash = "sha256:d61dbda892ee1220f28fb3663c08f6383c305db9f1f5624dc585c9cd05115027"},
- {file = "eth_rlp-1.0.1-py3-none-any.whl", hash = "sha256:dd76515d71654277377d48876b88e839d61553aaf56952e580bb7cebef2b1517"},
+ {file = "eth-rlp-2.1.0.tar.gz", hash = "sha256:d5b408a8cd20ed496e8e66d0559560d29bc21cee482f893936a1f05d0dddc4a0"},
+ {file = "eth_rlp-2.1.0-py3-none-any.whl", hash = "sha256:6f476eb7e37d81feaba5d98aed887e467be92648778c44b19fe594aea209cde1"},
]
[package.dependencies]
eth-utils = ">=2.0.0"
-hexbytes = ">=0.1.0,<1"
+hexbytes = ">=1.2.0"
rlp = ">=0.6.0"
-typing-extensions = {version = ">=4.0.1", markers = "python_version <= \"3.11\""}
[package.extras]
dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-hash[pycryptodome]", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"]
@@ -1007,13 +1137,13 @@ test = ["eth-hash[pycryptodome]", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"]
[[package]]
name = "eth-typing"
-version = "4.0.0"
+version = "4.2.3"
description = "eth-typing: Common type annotations for ethereum python packages"
optional = false
-python-versions = ">=3.8, <4"
+python-versions = "<4,>=3.8"
files = [
- {file = "eth-typing-4.0.0.tar.gz", hash = "sha256:9af0b6beafbc5c2e18daf19da5f5a68315023172c4e79d149e12ad10a3d3f731"},
- {file = "eth_typing-4.0.0-py3-none-any.whl", hash = "sha256:7e556bea322b6e8c0a231547b736c258e10ce9eed5ddc254f51031b12af66a16"},
+ {file = "eth_typing-4.2.3-py3-none-any.whl", hash = "sha256:b2df49fa89d2e85f2cc3fb1c903b0cd183d524f7a045e3db8cc720cf41adcd3d"},
+ {file = "eth_typing-4.2.3.tar.gz", hash = "sha256:8ee3ae7d4136d14fcb955c34f9dbef8e52170984d4dc68c0ab0d61621eab29d8"},
]
[package.extras]
@@ -1023,13 +1153,13 @@ test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"]
[[package]]
name = "eth-utils"
-version = "3.0.0"
+version = "4.1.1"
description = "eth-utils: Common utility functions for python code that interacts with Ethereum"
optional = false
-python-versions = ">=3.8, <4"
+python-versions = "<4,>=3.8"
files = [
- {file = "eth-utils-3.0.0.tar.gz", hash = "sha256:8721869568448349bceae63c277b75758d11e0dc190e7ef31e161b89619458f1"},
- {file = "eth_utils-3.0.0-py3-none-any.whl", hash = "sha256:9a284106acf6f6ce91ddf792489cf8bd4c681fd5ae7653d2f3d5d100be5c3905"},
+ {file = "eth_utils-4.1.1-py3-none-any.whl", hash = "sha256:ccbbac68a6d65cb6e294c5bcb6c6a5cec79a241c56dc5d9c345ed788c30f8534"},
+ {file = "eth_utils-4.1.1.tar.gz", hash = "sha256:71c8d10dec7494aeed20fa7a4d52ec2ce4a2e52fdce80aab4f5c3c19f3648b25"},
]
[package.dependencies]
@@ -1039,54 +1169,79 @@ eth-typing = ">=3.0.0"
toolz = {version = ">0.8.2", markers = "implementation_name == \"pypy\""}
[package.extras]
-dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-hash[pycryptodome]", "hypothesis (>=4.43.0)", "ipython", "mypy (==1.5.1)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"]
-docs = ["sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"]
+dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-hash[pycryptodome]", "hypothesis (>=4.43.0)", "ipython", "mypy (==1.5.1)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"]
+docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"]
test = ["hypothesis (>=4.43.0)", "mypy (==1.5.1)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"]
[[package]]
name = "fastapi"
-version = "0.110.0"
+version = "0.111.0"
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
optional = false
python-versions = ">=3.8"
files = [
- {file = "fastapi-0.110.0-py3-none-any.whl", hash = "sha256:87a1f6fb632a218222c5984be540055346a8f5d8a68e8f6fb647b1dc9934de4b"},
- {file = "fastapi-0.110.0.tar.gz", hash = "sha256:266775f0dcc95af9d3ef39bad55cff525329a931d5fd51930aadd4f428bf7ff3"},
+ {file = "fastapi-0.111.0-py3-none-any.whl", hash = "sha256:97ecbf994be0bcbdadedf88c3150252bed7b2087075ac99735403b1b76cc8fc0"},
+ {file = "fastapi-0.111.0.tar.gz", hash = "sha256:b9db9dd147c91cb8b769f7183535773d8741dd46f9dc6676cd82eab510228cd7"},
]
[package.dependencies]
+email_validator = ">=2.0.0"
+fastapi-cli = ">=0.0.2"
+httpx = ">=0.23.0"
+jinja2 = ">=2.11.2"
+orjson = ">=3.2.1"
pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0"
-starlette = ">=0.36.3,<0.37.0"
+python-multipart = ">=0.0.7"
+starlette = ">=0.37.2,<0.38.0"
typing-extensions = ">=4.8.0"
+ujson = ">=4.0.1,<4.0.2 || >4.0.2,<4.1.0 || >4.1.0,<4.2.0 || >4.2.0,<4.3.0 || >4.3.0,<5.0.0 || >5.0.0,<5.1.0 || >5.1.0"
+uvicorn = {version = ">=0.12.0", extras = ["standard"]}
+
+[package.extras]
+all = ["email_validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
+
+[[package]]
+name = "fastapi-cli"
+version = "0.0.4"
+description = "Run and manage FastAPI apps from the command line with FastAPI CLI. 🚀"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "fastapi_cli-0.0.4-py3-none-any.whl", hash = "sha256:a2552f3a7ae64058cdbb530be6fa6dbfc975dc165e4fa66d224c3d396e25e809"},
+ {file = "fastapi_cli-0.0.4.tar.gz", hash = "sha256:e2e9ffaffc1f7767f488d6da34b6f5a377751c996f397902eb6abb99a67bde32"},
+]
+
+[package.dependencies]
+typer = ">=0.12.3"
[package.extras]
-all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
+standard = ["fastapi", "uvicorn[standard] (>=0.15.0)"]
[[package]]
name = "filelock"
-version = "3.13.1"
+version = "3.14.0"
description = "A platform independent file lock."
optional = false
python-versions = ">=3.8"
files = [
- {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"},
- {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"},
+ {file = "filelock-3.14.0-py3-none-any.whl", hash = "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f"},
+ {file = "filelock-3.14.0.tar.gz", hash = "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a"},
]
[package.extras]
-docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"]
-testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"]
+docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"]
+testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"]
typing = ["typing-extensions (>=4.8)"]
[[package]]
name = "freezegun"
-version = "1.4.0"
+version = "1.5.1"
description = "Let your Python tests travel through time"
optional = false
python-versions = ">=3.7"
files = [
- {file = "freezegun-1.4.0-py3-none-any.whl", hash = "sha256:55e0fc3c84ebf0a96a5aa23ff8b53d70246479e9a68863f1fcac5a3e52f19dd6"},
- {file = "freezegun-1.4.0.tar.gz", hash = "sha256:10939b0ba0ff5adaecf3b06a5c2f73071d9678e507c5eaedb23c761d56ac774b"},
+ {file = "freezegun-1.5.1-py3-none-any.whl", hash = "sha256:bf111d7138a8abe55ab48a71755673dbaa4ab87f4cff5634a4442dfec34c15f1"},
+ {file = "freezegun-1.5.1.tar.gz", hash = "sha256:b29dedfcda6d5e8e083ce71b2b542753ad48cfec44037b3fc79702e2980a89e9"},
]
[package.dependencies]
@@ -1251,22 +1406,23 @@ test = ["objgraph", "psutil"]
[[package]]
name = "gunicorn"
-version = "21.2.0"
+version = "22.0.0"
description = "WSGI HTTP Server for UNIX"
optional = false
-python-versions = ">=3.5"
+python-versions = ">=3.7"
files = [
- {file = "gunicorn-21.2.0-py3-none-any.whl", hash = "sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0"},
- {file = "gunicorn-21.2.0.tar.gz", hash = "sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033"},
+ {file = "gunicorn-22.0.0-py3-none-any.whl", hash = "sha256:350679f91b24062c86e386e198a15438d53a7a8207235a78ba1b53df4c4378d9"},
+ {file = "gunicorn-22.0.0.tar.gz", hash = "sha256:4a0b436239ff76fb33f11c07a16482c521a7e09c1ce3cc293c2330afe01bec63"},
]
[package.dependencies]
packaging = "*"
[package.extras]
-eventlet = ["eventlet (>=0.24.1)"]
+eventlet = ["eventlet (>=0.24.1,!=0.36.0)"]
gevent = ["gevent (>=1.4.0)"]
setproctitle = ["setproctitle"]
+testing = ["coverage", "eventlet", "gevent", "pytest", "pytest-cov"]
tornado = ["tornado (>=0.2)"]
[[package]]
@@ -1282,30 +1438,29 @@ files = [
[[package]]
name = "hexbytes"
-version = "0.3.1"
+version = "1.2.0"
description = "hexbytes: Python `bytes` subclass that decodes hex, with a readable console output"
optional = false
-python-versions = ">=3.7, <4"
+python-versions = ">=3.8, <4"
files = [
- {file = "hexbytes-0.3.1-py3-none-any.whl", hash = "sha256:383595ad75026cf00abd570f44b368c6cdac0c6becfae5c39ff88829877f8a59"},
- {file = "hexbytes-0.3.1.tar.gz", hash = "sha256:a3fe35c6831ee8fafd048c4c086b986075fc14fd46258fa24ecb8d65745f9a9d"},
+ {file = "hexbytes-1.2.0-py3-none-any.whl", hash = "sha256:bb243ab58b8d8390e3a753fbc9e3616f0f958df43d874e19ae0e4b746722a7e9"},
+ {file = "hexbytes-1.2.0.tar.gz", hash = "sha256:965f1cc712e7b263c41fdf3fb36cf671ba6f59b895937cf33941a5c996ec3a5c"},
]
[package.extras]
-dev = ["black (>=22)", "bumpversion (>=0.5.3)", "eth-utils (>=1.0.1,<3)", "flake8 (==6.0.0)", "flake8-bugbear (==23.3.23)", "hypothesis (>=3.44.24,<=6.31.6)", "ipython", "isort (>=5.10.1)", "mypy (==0.971)", "pydocstyle (>=5.0.0)", "pytest (>=7.0.0)", "pytest-watch (>=4.1.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"]
-doc = ["sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"]
-lint = ["black (>=22)", "flake8 (==6.0.0)", "flake8-bugbear (==23.3.23)", "isort (>=5.10.1)", "mypy (==0.971)", "pydocstyle (>=5.0.0)"]
-test = ["eth-utils (>=1.0.1,<3)", "hypothesis (>=3.44.24,<=6.31.6)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"]
+dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-utils (>=2.0.0)", "hypothesis (>=3.44.24,<=6.31.6)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"]
+docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"]
+test = ["eth-utils (>=2.0.0)", "hypothesis (>=3.44.24,<=6.31.6)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"]
[[package]]
name = "httpcore"
-version = "1.0.4"
+version = "1.0.5"
description = "A minimal low-level HTTP client."
optional = false
python-versions = ">=3.8"
files = [
- {file = "httpcore-1.0.4-py3-none-any.whl", hash = "sha256:ac418c1db41bade2ad53ae2f3834a3a0f5ae76b56cf5aa497d2d033384fc7d73"},
- {file = "httpcore-1.0.4.tar.gz", hash = "sha256:cb2839ccfcba0d2d3c1131d3c3e26dfc327326fbe7a5dc0dbfe9f6c9151bb022"},
+ {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"},
+ {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"},
]
[package.dependencies]
@@ -1316,7 +1471,7 @@ h11 = ">=0.13,<0.15"
asyncio = ["anyio (>=4.0,<5.0)"]
http2 = ["h2 (>=3,<5)"]
socks = ["socksio (==1.*)"]
-trio = ["trio (>=0.22.0,<0.25.0)"]
+trio = ["trio (>=0.22.0,<0.26.0)"]
[[package]]
name = "httptools"
@@ -1395,7 +1550,7 @@ name = "ibet-prime-explorer"
version = "0.1.0"
description = "ibet-Prime Terminal UI for Block Chain Explorer"
optional = true
-python-versions = "3.11.2"
+python-versions = "3.12.2"
files = []
develop = true
@@ -1403,15 +1558,28 @@ develop = true
type = "directory"
url = "cmd/explorer"
+[[package]]
+name = "ibet-prime-settlement"
+version = "0.1.0"
+description = "ibet-Prime Settlement CLI"
+optional = true
+python-versions = "3.12.2"
+files = []
+develop = true
+
+[package.source]
+type = "directory"
+url = "cmd/settlement"
+
[[package]]
name = "identify"
-version = "2.5.35"
+version = "2.5.36"
description = "File identification library for Python"
optional = false
python-versions = ">=3.8"
files = [
- {file = "identify-2.5.35-py2.py3-none-any.whl", hash = "sha256:c4de0081837b211594f8e877a6b4fad7ca32bbfc1a9307fdd61c28bfe923f13e"},
- {file = "identify-2.5.35.tar.gz", hash = "sha256:10a7ca245cfcd756a554a7288159f72ff105ad233c7c4b9c6f0f4d108f5f6791"},
+ {file = "identify-2.5.36-py2.py3-none-any.whl", hash = "sha256:37d93f380f4de590500d9dba7db359d0d3da95ffe7f9de1753faa159e71e7dfa"},
+ {file = "identify-2.5.36.tar.gz", hash = "sha256:e5e00f54165f9047fbebeb4a560f9acfb8af4c88232be60a488e9b68d122745d"},
]
[package.extras]
@@ -1419,24 +1587,24 @@ license = ["ukkonen"]
[[package]]
name = "idna"
-version = "3.6"
+version = "3.7"
description = "Internationalized Domain Names in Applications (IDNA)"
optional = false
python-versions = ">=3.5"
files = [
- {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"},
- {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"},
+ {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"},
+ {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"},
]
[[package]]
name = "importlib-metadata"
-version = "7.0.2"
+version = "7.1.0"
description = "Read metadata from Python packages"
optional = false
python-versions = ">=3.8"
files = [
- {file = "importlib_metadata-7.0.2-py3-none-any.whl", hash = "sha256:f4bc4c0c070c490abf4ce96d715f68e95923320370efb66143df00199bb6c100"},
- {file = "importlib_metadata-7.0.2.tar.gz", hash = "sha256:198f568f3230878cb1b44fbd7975f87906c22336dba2e4a7f05278c281fbd792"},
+ {file = "importlib_metadata-7.1.0-py3-none-any.whl", hash = "sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570"},
+ {file = "importlib_metadata-7.1.0.tar.gz", hash = "sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2"},
]
[package.dependencies]
@@ -1445,7 +1613,7 @@ zipp = ">=0.5"
[package.extras]
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
perf = ["ipython"]
-testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"]
+testing = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"]
[[package]]
name = "iniconfig"
@@ -1473,51 +1641,33 @@ files = [
colors = ["colorama (>=0.4.6)"]
[[package]]
-name = "jmespath"
-version = "1.0.1"
-description = "JSON Matching Expressions"
+name = "jinja2"
+version = "3.1.4"
+description = "A very fast and expressive template engine."
optional = false
python-versions = ">=3.7"
files = [
- {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"},
- {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"},
-]
-
-[[package]]
-name = "jsonschema"
-version = "4.21.1"
-description = "An implementation of JSON Schema validation for Python"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "jsonschema-4.21.1-py3-none-any.whl", hash = "sha256:7996507afae316306f9e2290407761157c6f78002dcf7419acb99822143d1c6f"},
- {file = "jsonschema-4.21.1.tar.gz", hash = "sha256:85727c00279f5fa6bedbe6238d2aa6403bedd8b4864ab11207d07df3cc1b2ee5"},
+ {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"},
+ {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"},
]
[package.dependencies]
-attrs = ">=22.2.0"
-jsonschema-specifications = ">=2023.03.6"
-referencing = ">=0.28.4"
-rpds-py = ">=0.7.1"
+MarkupSafe = ">=2.0"
[package.extras]
-format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"]
-format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"]
+i18n = ["Babel (>=2.7)"]
[[package]]
-name = "jsonschema-specifications"
-version = "2023.12.1"
-description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry"
+name = "jmespath"
+version = "1.0.1"
+description = "JSON Matching Expressions"
optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.7"
files = [
- {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"},
- {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"},
+ {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"},
+ {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"},
]
-[package.dependencies]
-referencing = ">=0.31.0"
-
[[package]]
name = "linkify-it-py"
version = "2.0.3"
@@ -1538,109 +1688,15 @@ dev = ["black", "flake8", "isort", "pre-commit", "pyproject-flake8"]
doc = ["myst-parser", "sphinx", "sphinx-book-theme"]
test = ["coverage", "pytest", "pytest-cov"]
-[[package]]
-name = "lru-dict"
-version = "1.2.0"
-description = "An Dict like LRU container."
-optional = false
-python-versions = "*"
-files = [
- {file = "lru-dict-1.2.0.tar.gz", hash = "sha256:13c56782f19d68ddf4d8db0170041192859616514c706b126d0df2ec72a11bd7"},
- {file = "lru_dict-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:de906e5486b5c053d15b7731583c25e3c9147c288ac8152a6d1f9bccdec72641"},
- {file = "lru_dict-1.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:604d07c7604b20b3130405d137cae61579578b0e8377daae4125098feebcb970"},
- {file = "lru_dict-1.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:203b3e78d03d88f491fa134f85a42919020686b6e6f2d09759b2f5517260c651"},
- {file = "lru_dict-1.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:020b93870f8c7195774cbd94f033b96c14f51c57537969965c3af300331724fe"},
- {file = "lru_dict-1.2.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1184d91cfebd5d1e659d47f17a60185bbf621635ca56dcdc46c6a1745d25df5c"},
- {file = "lru_dict-1.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:fc42882b554a86e564e0b662da47b8a4b32fa966920bd165e27bb8079a323bc1"},
- {file = "lru_dict-1.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:18ee88ada65bd2ffd483023be0fa1c0a6a051ef666d1cd89e921dcce134149f2"},
- {file = "lru_dict-1.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:756230c22257597b7557eaef7f90484c489e9ba78e5bb6ab5a5bcfb6b03cb075"},
- {file = "lru_dict-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c4da599af36618881748b5db457d937955bb2b4800db891647d46767d636c408"},
- {file = "lru_dict-1.2.0-cp310-cp310-win32.whl", hash = "sha256:35a142a7d1a4fd5d5799cc4f8ab2fff50a598d8cee1d1c611f50722b3e27874f"},
- {file = "lru_dict-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:6da5b8099766c4da3bf1ed6e7d7f5eff1681aff6b5987d1258a13bd2ed54f0c9"},
- {file = "lru_dict-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b20b7c9beb481e92e07368ebfaa363ed7ef61e65ffe6e0edbdbaceb33e134124"},
- {file = "lru_dict-1.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22147367b296be31cc858bf167c448af02435cac44806b228c9be8117f1bfce4"},
- {file = "lru_dict-1.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:34a3091abeb95e707f381a8b5b7dc8e4ee016316c659c49b726857b0d6d1bd7a"},
- {file = "lru_dict-1.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:877801a20f05c467126b55338a4e9fa30e2a141eb7b0b740794571b7d619ee11"},
- {file = "lru_dict-1.2.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d3336e901acec897bcd318c42c2b93d5f1d038e67688f497045fc6bad2c0be7"},
- {file = "lru_dict-1.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8dafc481d2defb381f19b22cc51837e8a42631e98e34b9e0892245cc96593deb"},
- {file = "lru_dict-1.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:87bbad3f5c3de8897b8c1263a9af73bbb6469fb90e7b57225dad89b8ef62cd8d"},
- {file = "lru_dict-1.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:25f9e0bc2fe8f41c2711ccefd2871f8a5f50a39e6293b68c3dec576112937aad"},
- {file = "lru_dict-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ae301c282a499dc1968dd633cfef8771dd84228ae9d40002a3ea990e4ff0c469"},
- {file = "lru_dict-1.2.0-cp311-cp311-win32.whl", hash = "sha256:c9617583173a29048e11397f165501edc5ae223504a404b2532a212a71ecc9ed"},
- {file = "lru_dict-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6b7a031e47421d4b7aa626b8c91c180a9f037f89e5d0a71c4bb7afcf4036c774"},
- {file = "lru_dict-1.2.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ea2ac3f7a7a2f32f194c84d82a034e66780057fd908b421becd2f173504d040e"},
- {file = "lru_dict-1.2.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd46c94966f631a81ffe33eee928db58e9fbee15baba5923d284aeadc0e0fa76"},
- {file = "lru_dict-1.2.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:086ce993414f0b28530ded7e004c77dc57c5748fa6da488602aa6e7f79e6210e"},
- {file = "lru_dict-1.2.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df25a426446197488a6702954dcc1de511deee20c9db730499a2aa83fddf0df1"},
- {file = "lru_dict-1.2.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c53b12b89bd7a6c79f0536ff0d0a84fdf4ab5f6252d94b24b9b753bd9ada2ddf"},
- {file = "lru_dict-1.2.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:f9484016e6765bd295708cccc9def49f708ce07ac003808f69efa386633affb9"},
- {file = "lru_dict-1.2.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:d0f7ec902a0097ac39f1922c89be9eaccf00eb87751e28915320b4f72912d057"},
- {file = "lru_dict-1.2.0-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:981ef3edc82da38d39eb60eae225b88a538d47b90cce2e5808846fd2cf64384b"},
- {file = "lru_dict-1.2.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e25b2e90a032dc248213af7f3f3e975e1934b204f3b16aeeaeaff27a3b65e128"},
- {file = "lru_dict-1.2.0-cp36-cp36m-win32.whl", hash = "sha256:59f3df78e94e07959f17764e7fa7ca6b54e9296953d2626a112eab08e1beb2db"},
- {file = "lru_dict-1.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:de24b47159e07833aeab517d9cb1c3c5c2d6445cc378b1c2f1d8d15fb4841d63"},
- {file = "lru_dict-1.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d0dd4cd58220351233002f910e35cc01d30337696b55c6578f71318b137770f9"},
- {file = "lru_dict-1.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a87bdc291718bbdf9ea4be12ae7af26cbf0706fa62c2ac332748e3116c5510a7"},
- {file = "lru_dict-1.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05fb8744f91f58479cbe07ed80ada6696ec7df21ea1740891d4107a8dd99a970"},
- {file = "lru_dict-1.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00f6e8a3fc91481b40395316a14c94daa0f0a5de62e7e01a7d589f8d29224052"},
- {file = "lru_dict-1.2.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b172fce0a0ffc0fa6d282c14256d5a68b5db1e64719c2915e69084c4b6bf555"},
- {file = "lru_dict-1.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:e707d93bae8f0a14e6df1ae8b0f076532b35f00e691995f33132d806a88e5c18"},
- {file = "lru_dict-1.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b9ec7a4a0d6b8297102aa56758434fb1fca276a82ed7362e37817407185c3abb"},
- {file = "lru_dict-1.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:f404dcc8172da1f28da9b1f0087009578e608a4899b96d244925c4f463201f2a"},
- {file = "lru_dict-1.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1171ad3bff32aa8086778be4a3bdff595cc2692e78685bcce9cb06b96b22dcc2"},
- {file = "lru_dict-1.2.0-cp37-cp37m-win32.whl", hash = "sha256:0c316dfa3897fabaa1fe08aae89352a3b109e5f88b25529bc01e98ac029bf878"},
- {file = "lru_dict-1.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5919dd04446bc1ee8d6ecda2187deeebfff5903538ae71083e069bc678599446"},
- {file = "lru_dict-1.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fbf36c5a220a85187cacc1fcb7dd87070e04b5fc28df7a43f6842f7c8224a388"},
- {file = "lru_dict-1.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:712e71b64da181e1c0a2eaa76cd860265980cd15cb0e0498602b8aa35d5db9f8"},
- {file = "lru_dict-1.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f54908bf91280a9b8fa6a8c8f3c2f65850ce6acae2852bbe292391628ebca42f"},
- {file = "lru_dict-1.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3838e33710935da2ade1dd404a8b936d571e29268a70ff4ca5ba758abb3850df"},
- {file = "lru_dict-1.2.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5d5a5f976b39af73324f2b793862859902ccb9542621856d51a5993064f25e4"},
- {file = "lru_dict-1.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8bda3a9afd241ee0181661decaae25e5336ce513ac268ab57da737eacaa7871f"},
- {file = "lru_dict-1.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:bd2cd1b998ea4c8c1dad829fc4fa88aeed4dee555b5e03c132fc618e6123f168"},
- {file = "lru_dict-1.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:b55753ee23028ba8644fd22e50de7b8f85fa60b562a0fafaad788701d6131ff8"},
- {file = "lru_dict-1.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7e51fa6a203fa91d415f3b2900e5748ec8e06ad75777c98cc3aeb3983ca416d7"},
- {file = "lru_dict-1.2.0-cp38-cp38-win32.whl", hash = "sha256:cd6806313606559e6c7adfa0dbeb30fc5ab625f00958c3d93f84831e7a32b71e"},
- {file = "lru_dict-1.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:5d90a70c53b0566084447c3ef9374cc5a9be886e867b36f89495f211baabd322"},
- {file = "lru_dict-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a3ea7571b6bf2090a85ff037e6593bbafe1a8598d5c3b4560eb56187bcccb4dc"},
- {file = "lru_dict-1.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:287c2115a59c1c9ed0d5d8ae7671e594b1206c36ea9df2fca6b17b86c468ff99"},
- {file = "lru_dict-1.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b5ccfd2291c93746a286c87c3f895165b697399969d24c54804ec3ec559d4e43"},
- {file = "lru_dict-1.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b710f0f4d7ec4f9fa89dfde7002f80bcd77de8024017e70706b0911ea086e2ef"},
- {file = "lru_dict-1.2.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5345bf50e127bd2767e9fd42393635bbc0146eac01f6baf6ef12c332d1a6a329"},
- {file = "lru_dict-1.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:291d13f85224551913a78fe695cde04cbca9dcb1d84c540167c443eb913603c9"},
- {file = "lru_dict-1.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d5bb41bc74b321789803d45b124fc2145c1b3353b4ad43296d9d1d242574969b"},
- {file = "lru_dict-1.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0facf49b053bf4926d92d8d5a46fe07eecd2af0441add0182c7432d53d6da667"},
- {file = "lru_dict-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:987b73a06bcf5a95d7dc296241c6b1f9bc6cda42586948c9dabf386dc2bef1cd"},
- {file = "lru_dict-1.2.0-cp39-cp39-win32.whl", hash = "sha256:231d7608f029dda42f9610e5723614a35b1fff035a8060cf7d2be19f1711ace8"},
- {file = "lru_dict-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:71da89e134747e20ed5b8ad5b4ee93fc5b31022c2b71e8176e73c5a44699061b"},
- {file = "lru_dict-1.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:21b3090928c7b6cec509e755cc3ab742154b33660a9b433923bd12c37c448e3e"},
- {file = "lru_dict-1.2.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaecd7085212d0aa4cd855f38b9d61803d6509731138bf798a9594745953245b"},
- {file = "lru_dict-1.2.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ead83ac59a29d6439ddff46e205ce32f8b7f71a6bd8062347f77e232825e3d0a"},
- {file = "lru_dict-1.2.0-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:312b6b2a30188586fe71358f0f33e4bac882d33f5e5019b26f084363f42f986f"},
- {file = "lru_dict-1.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:b30122e098c80e36d0117810d46459a46313421ce3298709170b687dc1240b02"},
- {file = "lru_dict-1.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f010cfad3ab10676e44dc72a813c968cd586f37b466d27cde73d1f7f1ba158c2"},
- {file = "lru_dict-1.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20f5f411f7751ad9a2c02e80287cedf69ae032edd321fe696e310d32dd30a1f8"},
- {file = "lru_dict-1.2.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:afdadd73304c9befaed02eb42f5f09fdc16288de0a08b32b8080f0f0f6350aa6"},
- {file = "lru_dict-1.2.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7ab0c10c4fa99dc9e26b04e6b62ac32d2bcaea3aad9b81ec8ce9a7aa32b7b1b"},
- {file = "lru_dict-1.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:edad398d5d402c43d2adada390dd83c74e46e020945ff4df801166047013617e"},
- {file = "lru_dict-1.2.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:91d577a11b84387013815b1ad0bb6e604558d646003b44c92b3ddf886ad0f879"},
- {file = "lru_dict-1.2.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb12f19cdf9c4f2d9aa259562e19b188ff34afab28dd9509ff32a3f1c2c29326"},
- {file = "lru_dict-1.2.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e4c85aa8844bdca3c8abac3b7f78da1531c74e9f8b3e4890c6e6d86a5a3f6c0"},
- {file = "lru_dict-1.2.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c6acbd097b15bead4de8e83e8a1030bb4d8257723669097eac643a301a952f0"},
- {file = "lru_dict-1.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b6613daa851745dd22b860651de930275be9d3e9373283a2164992abacb75b62"},
-]
-
-[package.extras]
-test = ["pytest"]
-
[[package]]
name = "mako"
-version = "1.3.2"
+version = "1.3.5"
description = "A super-fast templating language that borrows the best ideas from the existing templating languages."
optional = false
python-versions = ">=3.8"
files = [
- {file = "Mako-1.3.2-py3-none-any.whl", hash = "sha256:32a99d70754dfce237019d17ffe4a282d2d3351b9c476e90d8a60e63f133b80c"},
- {file = "Mako-1.3.2.tar.gz", hash = "sha256:2a0c8ad7f6274271b3bb7467dd37cf9cc6dab4bc19cb69a4ef10669402de698e"},
+ {file = "Mako-1.3.5-py3-none-any.whl", hash = "sha256:260f1dbc3a519453a9c856dedfe4beb4e50bd5a26d96386cb6c80856556bb91a"},
+ {file = "Mako-1.3.5.tar.gz", hash = "sha256:48dbc20568c1d276a2698b36d968fa76161bf127194907ea6fc594fa81f943bc"},
]
[package.dependencies]
@@ -1748,13 +1804,13 @@ files = [
[[package]]
name = "mdit-py-plugins"
-version = "0.4.0"
+version = "0.4.1"
description = "Collection of plugins for markdown-it-py"
optional = false
python-versions = ">=3.8"
files = [
- {file = "mdit_py_plugins-0.4.0-py3-none-any.whl", hash = "sha256:b51b3bb70691f57f974e257e367107857a93b36f322a9e6d44ca5bf28ec2def9"},
- {file = "mdit_py_plugins-0.4.0.tar.gz", hash = "sha256:d8ab27e9aed6c38aa716819fedfde15ca275715955f8a185a8e1cf90fb1d2c1b"},
+ {file = "mdit_py_plugins-0.4.1-py3-none-any.whl", hash = "sha256:1020dfe4e6bfc2c79fb49ae4e3f5b297f5ccd20f010187acc52af2921e27dc6a"},
+ {file = "mdit_py_plugins-0.4.1.tar.gz", hash = "sha256:834b8ac23d1cd60cec703646ffd22ae97b7955a6d596eb1d304be1e251ae499c"},
]
[package.dependencies]
@@ -1776,6 +1832,64 @@ files = [
{file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"},
]
+[[package]]
+name = "memray"
+version = "1.12.0"
+description = "A memory profiler for Python applications"
+optional = false
+python-versions = ">=3.7.0"
+files = [
+ {file = "memray-1.12.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:27b6ad53081b2f588485393df6498be6d07c2331435625472dc6111b265bef44"},
+ {file = "memray-1.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:64b4e881262c60768ddfbbf062f3861f2bd0cd04414d4ee4cf4f8834285d3d7c"},
+ {file = "memray-1.12.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:df79afd83b4c3b5139c7d47ca1d40f5859d7c5be38759a4a698de181414b7cd6"},
+ {file = "memray-1.12.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:28f543f5c42491e233dbcb4c87da4a890cef1634b1cd6d0746092d74dc5adcb0"},
+ {file = "memray-1.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a2ad07e0a0bcf15772f7887a1739e1e0679223ee4025493e0011ef35e30aa75"},
+ {file = "memray-1.12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:621ceb522614e0076fdec78ad4d4ef34de6eeb62f63bbdd6a27c56d5ef07bde8"},
+ {file = "memray-1.12.0-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:ff94c5471d72e616d9b80f7d5b7839b9de740088f04b2b5a13eb457d571db073"},
+ {file = "memray-1.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:21ec3d82f9535dd66bdad2a33aeb46ebc03801b7d9db1f4ca1c96bc96d2c6253"},
+ {file = "memray-1.12.0-cp311-cp311-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7ab5d0d7c566fc5f9bec28276a5219b20e6b5df4cdce16e506d9eda6cbb207e1"},
+ {file = "memray-1.12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7252b98ca98e0ce6f95ad81d161f468ce9ada12e66e64e18e8e7c3b95b203035"},
+ {file = "memray-1.12.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3abf058226e72caef0d68f2e850954668305934c20d2ccfef89c3eac2ccf7a40"},
+ {file = "memray-1.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3236d5fbc2576847d6c40741b61f6fa2fe5b0079011c4d3843bd9fc3d0b86ba7"},
+ {file = "memray-1.12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:df5ac32d9e4458af1a8c7d6864095c8dd3bbbad4978fead3dd2d939368b1606b"},
+ {file = "memray-1.12.0-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:22f10a95e74675ce96ae29e968a978e27b9ce466bdcaa322c15edb6ea6ff661a"},
+ {file = "memray-1.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fcfe985ce1b019987258a2edb71edc07a38d96d9c0ab28a91880b1e048b68d8e"},
+ {file = "memray-1.12.0-cp312-cp312-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ef93e74548d55533f02f7e27417f88e2606f54f5cfd58ed84e0f2d6839e4ad48"},
+ {file = "memray-1.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a60d2a70077f091f51d9bacb387d5f3d9db37a409ab6b071398a5b5eccffe3ec"},
+ {file = "memray-1.12.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee72ca364f65f8a74da2c16c17ffb6768331fae9a14bec955932d2a3203c389d"},
+ {file = "memray-1.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8da8a7088b7b434d77ee40c843c5a66c4c10ded711f876122fb661265a950250"},
+ {file = "memray-1.12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0a43b7ea24db0469b26dd2da6058f24bd0882fae35eaff9eb3dd572234869771"},
+ {file = "memray-1.12.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2be213607228a56ee2e9de598cd4b14aded45e19d404fba1945d2008fd4e0bb6"},
+ {file = "memray-1.12.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a7fd3e5f614666faa380a3094ac03793ada9c69239ea4a4716e929efaa7d8ff4"},
+ {file = "memray-1.12.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57f04aeba911dd082c7c057e79bb338449621e58ae4e885dde05b5a45d6edcac"},
+ {file = "memray-1.12.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dcc2f96f7cdd0a7bbfd86dafad4e76bb6adc4f41560f474185c8722ed6e653d1"},
+ {file = "memray-1.12.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:d3367e3748c64797c4986fa543e784067c5de08037621f5f1e628d6fc98cefe5"},
+ {file = "memray-1.12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:dee3eff75b6a47841fb58c909723c140e72915de24a712e1ee4c157c3e1b44af"},
+ {file = "memray-1.12.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2bdbcd44e31fe27822b1920814f87c9cc305d731d38c5d32d93f5f9bfa797a9e"},
+ {file = "memray-1.12.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:702a502b8c9a2ca64a34605aa32381f94c6443ba6608a6bf877e10f94d342de9"},
+ {file = "memray-1.12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8031156adf4a4ab471c5b835bfa773e2d36a3bbf4338236969d8c0b9d76beda"},
+ {file = "memray-1.12.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8e0dd3e4440c9d64e174cc9663cb6a8ccefa0f45ee967b4de3c31f1d620008e9"},
+ {file = "memray-1.12.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:ae2176753be2157235ad766ec662cd98f1d78de2581b30366942c696b9f8da05"},
+ {file = "memray-1.12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f464861ddce2d4322412f2d408b796027716a623ef67ada9e4fb95300691dd52"},
+ {file = "memray-1.12.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e6760685eb69997c8684358f1070c7252929b2b0e0863ed9adf7c684dc6cdf99"},
+ {file = "memray-1.12.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2f39ad9fc06ddc6f9e506e05a2e4036a6678447673f9134a1827266485a124b"},
+ {file = "memray-1.12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5693b6210c51f1e66ce33a8d6a6fb5bd84c83a3fca644244c7f417e74cc93480"},
+ {file = "memray-1.12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bf282a90f0f01ee419d4c184416ae22f7e26450dd80897fb7998633ffde4ffab"},
+ {file = "memray-1.12.0.tar.gz", hash = "sha256:3b61c199a60197ae6164a2b44cd828c52de24083ecc49e9ac7d6287686bd68f3"},
+]
+
+[package.dependencies]
+jinja2 = ">=2.9"
+rich = ">=11.2.0"
+textual = ">=0.41.0"
+
+[package.extras]
+benchmark = ["asv"]
+dev = ["Cython", "IPython", "asv", "black", "bump2version", "check-manifest", "flake8", "furo", "greenlet", "ipython", "isort", "mypy", "pytest", "pytest-cov", "pytest-textual-snapshot", "setuptools", "sphinx", "sphinx-argparse", "towncrier"]
+docs = ["IPython", "bump2version", "furo", "sphinx", "sphinx-argparse", "towncrier"]
+lint = ["black", "check-manifest", "flake8", "isort", "mypy"]
+test = ["Cython", "greenlet", "ipython", "pytest", "pytest-cov", "pytest-textual-snapshot", "setuptools"]
+
[[package]]
name = "msgpack"
version = "1.0.8"
@@ -1953,75 +2067,68 @@ files = [
[[package]]
name = "nodeenv"
-version = "1.8.0"
+version = "1.9.0"
description = "Node.js virtual environment builder"
optional = false
-python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
files = [
- {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"},
- {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"},
+ {file = "nodeenv-1.9.0-py2.py3-none-any.whl", hash = "sha256:508ecec98f9f3330b636d4448c0f1a56fc68017c68f1e7857ebc52acf0eb879a"},
+ {file = "nodeenv-1.9.0.tar.gz", hash = "sha256:07f144e90dae547bf0d4ee8da0ee42664a42a04e02ed68e06324348dafe4bdb1"},
]
-[package.dependencies]
-setuptools = "*"
-
[[package]]
name = "orjson"
-version = "3.9.15"
+version = "3.10.3"
description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy"
optional = false
python-versions = ">=3.8"
files = [
- {file = "orjson-3.9.15-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:d61f7ce4727a9fa7680cd6f3986b0e2c732639f46a5e0156e550e35258aa313a"},
- {file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4feeb41882e8aa17634b589533baafdceb387e01e117b1ec65534ec724023d04"},
- {file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fbbeb3c9b2edb5fd044b2a070f127a0ac456ffd079cb82746fc84af01ef021a4"},
- {file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b66bcc5670e8a6b78f0313bcb74774c8291f6f8aeef10fe70e910b8040f3ab75"},
- {file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2973474811db7b35c30248d1129c64fd2bdf40d57d84beed2a9a379a6f57d0ab"},
- {file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fe41b6f72f52d3da4db524c8653e46243c8c92df826ab5ffaece2dba9cccd58"},
- {file = "orjson-3.9.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4228aace81781cc9d05a3ec3a6d2673a1ad0d8725b4e915f1089803e9efd2b99"},
- {file = "orjson-3.9.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6f7b65bfaf69493c73423ce9db66cfe9138b2f9ef62897486417a8fcb0a92bfe"},
- {file = "orjson-3.9.15-cp310-none-win32.whl", hash = "sha256:2d99e3c4c13a7b0fb3792cc04c2829c9db07838fb6973e578b85c1745e7d0ce7"},
- {file = "orjson-3.9.15-cp310-none-win_amd64.whl", hash = "sha256:b725da33e6e58e4a5d27958568484aa766e825e93aa20c26c91168be58e08cbb"},
- {file = "orjson-3.9.15-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:c8e8fe01e435005d4421f183038fc70ca85d2c1e490f51fb972db92af6e047c2"},
- {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87f1097acb569dde17f246faa268759a71a2cb8c96dd392cd25c668b104cad2f"},
- {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff0f9913d82e1d1fadbd976424c316fbc4d9c525c81d047bbdd16bd27dd98cfc"},
- {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8055ec598605b0077e29652ccfe9372247474375e0e3f5775c91d9434e12d6b1"},
- {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6768a327ea1ba44c9114dba5fdda4a214bdb70129065cd0807eb5f010bfcbb5"},
- {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12365576039b1a5a47df01aadb353b68223da413e2e7f98c02403061aad34bde"},
- {file = "orjson-3.9.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:71c6b009d431b3839d7c14c3af86788b3cfac41e969e3e1c22f8a6ea13139404"},
- {file = "orjson-3.9.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e18668f1bd39e69b7fed19fa7cd1cd110a121ec25439328b5c89934e6d30d357"},
- {file = "orjson-3.9.15-cp311-none-win32.whl", hash = "sha256:62482873e0289cf7313461009bf62ac8b2e54bc6f00c6fabcde785709231a5d7"},
- {file = "orjson-3.9.15-cp311-none-win_amd64.whl", hash = "sha256:b3d336ed75d17c7b1af233a6561cf421dee41d9204aa3cfcc6c9c65cd5bb69a8"},
- {file = "orjson-3.9.15-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:82425dd5c7bd3adfe4e94c78e27e2fa02971750c2b7ffba648b0f5d5cc016a73"},
- {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c51378d4a8255b2e7c1e5cc430644f0939539deddfa77f6fac7b56a9784160a"},
- {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6ae4e06be04dc00618247c4ae3f7c3e561d5bc19ab6941427f6d3722a0875ef7"},
- {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bcef128f970bb63ecf9a65f7beafd9b55e3aaf0efc271a4154050fc15cdb386e"},
- {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b72758f3ffc36ca566ba98a8e7f4f373b6c17c646ff8ad9b21ad10c29186f00d"},
- {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c57bc7b946cf2efa67ac55766e41764b66d40cbd9489041e637c1304400494"},
- {file = "orjson-3.9.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:946c3a1ef25338e78107fba746f299f926db408d34553b4754e90a7de1d44068"},
- {file = "orjson-3.9.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2f256d03957075fcb5923410058982aea85455d035607486ccb847f095442bda"},
- {file = "orjson-3.9.15-cp312-none-win_amd64.whl", hash = "sha256:5bb399e1b49db120653a31463b4a7b27cf2fbfe60469546baf681d1b39f4edf2"},
- {file = "orjson-3.9.15-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:b17f0f14a9c0ba55ff6279a922d1932e24b13fc218a3e968ecdbf791b3682b25"},
- {file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f6cbd8e6e446fb7e4ed5bac4661a29e43f38aeecbf60c4b900b825a353276a1"},
- {file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:76bc6356d07c1d9f4b782813094d0caf1703b729d876ab6a676f3aaa9a47e37c"},
- {file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fdfa97090e2d6f73dced247a2f2d8004ac6449df6568f30e7fa1a045767c69a6"},
- {file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7413070a3e927e4207d00bd65f42d1b780fb0d32d7b1d951f6dc6ade318e1b5a"},
- {file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9cf1596680ac1f01839dba32d496136bdd5d8ffb858c280fa82bbfeb173bdd40"},
- {file = "orjson-3.9.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:809d653c155e2cc4fd39ad69c08fdff7f4016c355ae4b88905219d3579e31eb7"},
- {file = "orjson-3.9.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:920fa5a0c5175ab14b9c78f6f820b75804fb4984423ee4c4f1e6d748f8b22bc1"},
- {file = "orjson-3.9.15-cp38-none-win32.whl", hash = "sha256:2b5c0f532905e60cf22a511120e3719b85d9c25d0e1c2a8abb20c4dede3b05a5"},
- {file = "orjson-3.9.15-cp38-none-win_amd64.whl", hash = "sha256:67384f588f7f8daf040114337d34a5188346e3fae6c38b6a19a2fe8c663a2f9b"},
- {file = "orjson-3.9.15-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:6fc2fe4647927070df3d93f561d7e588a38865ea0040027662e3e541d592811e"},
- {file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34cbcd216e7af5270f2ffa63a963346845eb71e174ea530867b7443892d77180"},
- {file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f541587f5c558abd93cb0de491ce99a9ef8d1ae29dd6ab4dbb5a13281ae04cbd"},
- {file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92255879280ef9c3c0bcb327c5a1b8ed694c290d61a6a532458264f887f052cb"},
- {file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:05a1f57fb601c426635fcae9ddbe90dfc1ed42245eb4c75e4960440cac667262"},
- {file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ede0bde16cc6e9b96633df1631fbcd66491d1063667f260a4f2386a098393790"},
- {file = "orjson-3.9.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e88b97ef13910e5f87bcbc4dd7979a7de9ba8702b54d3204ac587e83639c0c2b"},
- {file = "orjson-3.9.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57d5d8cf9c27f7ef6bc56a5925c7fbc76b61288ab674eb352c26ac780caa5b10"},
- {file = "orjson-3.9.15-cp39-none-win32.whl", hash = "sha256:001f4eb0ecd8e9ebd295722d0cbedf0748680fb9998d3993abaed2f40587257a"},
- {file = "orjson-3.9.15-cp39-none-win_amd64.whl", hash = "sha256:ea0b183a5fe6b2b45f3b854b0d19c4e932d6f5934ae1f723b07cf9560edd4ec7"},
- {file = "orjson-3.9.15.tar.gz", hash = "sha256:95cae920959d772f30ab36d3b25f83bb0f3be671e986c72ce22f8fa700dae061"},
+ {file = "orjson-3.10.3-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9fb6c3f9f5490a3eb4ddd46fc1b6eadb0d6fc16fb3f07320149c3286a1409dd8"},
+ {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:252124b198662eee80428f1af8c63f7ff077c88723fe206a25df8dc57a57b1fa"},
+ {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9f3e87733823089a338ef9bbf363ef4de45e5c599a9bf50a7a9b82e86d0228da"},
+ {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8334c0d87103bb9fbbe59b78129f1f40d1d1e8355bbed2ca71853af15fa4ed3"},
+ {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1952c03439e4dce23482ac846e7961f9d4ec62086eb98ae76d97bd41d72644d7"},
+ {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c0403ed9c706dcd2809f1600ed18f4aae50be263bd7112e54b50e2c2bc3ebd6d"},
+ {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:382e52aa4270a037d41f325e7d1dfa395b7de0c367800b6f337d8157367bf3a7"},
+ {file = "orjson-3.10.3-cp310-none-win32.whl", hash = "sha256:be2aab54313752c04f2cbaab4515291ef5af8c2256ce22abc007f89f42f49109"},
+ {file = "orjson-3.10.3-cp310-none-win_amd64.whl", hash = "sha256:416b195f78ae461601893f482287cee1e3059ec49b4f99479aedf22a20b1098b"},
+ {file = "orjson-3.10.3-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:73100d9abbbe730331f2242c1fc0bcb46a3ea3b4ae3348847e5a141265479700"},
+ {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a12eee96e3ab828dbfcb4d5a0023aa971b27143a1d35dc214c176fdfb29b3"},
+ {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:520de5e2ef0b4ae546bea25129d6c7c74edb43fc6cf5213f511a927f2b28148b"},
+ {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccaa0a401fc02e8828a5bedfd80f8cd389d24f65e5ca3954d72c6582495b4bcf"},
+ {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7bc9e8bc11bac40f905640acd41cbeaa87209e7e1f57ade386da658092dc16"},
+ {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3582b34b70543a1ed6944aca75e219e1192661a63da4d039d088a09c67543b08"},
+ {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c23dfa91481de880890d17aa7b91d586a4746a4c2aa9a145bebdbaf233768d5"},
+ {file = "orjson-3.10.3-cp311-none-win32.whl", hash = "sha256:1770e2a0eae728b050705206d84eda8b074b65ee835e7f85c919f5705b006c9b"},
+ {file = "orjson-3.10.3-cp311-none-win_amd64.whl", hash = "sha256:93433b3c1f852660eb5abdc1f4dd0ced2be031ba30900433223b28ee0140cde5"},
+ {file = "orjson-3.10.3-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a39aa73e53bec8d410875683bfa3a8edf61e5a1c7bb4014f65f81d36467ea098"},
+ {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0943a96b3fa09bee1afdfccc2cb236c9c64715afa375b2af296c73d91c23eab2"},
+ {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e852baafceff8da3c9defae29414cc8513a1586ad93e45f27b89a639c68e8176"},
+ {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18566beb5acd76f3769c1d1a7ec06cdb81edc4d55d2765fb677e3eaa10fa99e0"},
+ {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bd2218d5a3aa43060efe649ec564ebedec8ce6ae0a43654b81376216d5ebd42"},
+ {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cf20465e74c6e17a104ecf01bf8cd3b7b252565b4ccee4548f18b012ff2f8069"},
+ {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ba7f67aa7f983c4345eeda16054a4677289011a478ca947cd69c0a86ea45e534"},
+ {file = "orjson-3.10.3-cp312-none-win32.whl", hash = "sha256:17e0713fc159abc261eea0f4feda611d32eabc35708b74bef6ad44f6c78d5ea0"},
+ {file = "orjson-3.10.3-cp312-none-win_amd64.whl", hash = "sha256:4c895383b1ec42b017dd2c75ae8a5b862fc489006afde06f14afbdd0309b2af0"},
+ {file = "orjson-3.10.3-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:be2719e5041e9fb76c8c2c06b9600fe8e8584e6980061ff88dcbc2691a16d20d"},
+ {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0175a5798bdc878956099f5c54b9837cb62cfbf5d0b86ba6d77e43861bcec2"},
+ {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:978be58a68ade24f1af7758626806e13cff7748a677faf95fbb298359aa1e20d"},
+ {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16bda83b5c61586f6f788333d3cf3ed19015e3b9019188c56983b5a299210eb5"},
+ {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ad1f26bea425041e0a1adad34630c4825a9e3adec49079b1fb6ac8d36f8b754"},
+ {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9e253498bee561fe85d6325ba55ff2ff08fb5e7184cd6a4d7754133bd19c9195"},
+ {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0a62f9968bab8a676a164263e485f30a0b748255ee2f4ae49a0224be95f4532b"},
+ {file = "orjson-3.10.3-cp38-none-win32.whl", hash = "sha256:8d0b84403d287d4bfa9bf7d1dc298d5c1c5d9f444f3737929a66f2fe4fb8f134"},
+ {file = "orjson-3.10.3-cp38-none-win_amd64.whl", hash = "sha256:8bc7a4df90da5d535e18157220d7915780d07198b54f4de0110eca6b6c11e290"},
+ {file = "orjson-3.10.3-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9059d15c30e675a58fdcd6f95465c1522b8426e092de9fff20edebfdc15e1cb0"},
+ {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d40c7f7938c9c2b934b297412c067936d0b54e4b8ab916fd1a9eb8f54c02294"},
+ {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4a654ec1de8fdaae1d80d55cee65893cb06494e124681ab335218be6a0691e7"},
+ {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:831c6ef73f9aa53c5f40ae8f949ff7681b38eaddb6904aab89dca4d85099cb78"},
+ {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99b880d7e34542db89f48d14ddecbd26f06838b12427d5a25d71baceb5ba119d"},
+ {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2e5e176c994ce4bd434d7aafb9ecc893c15f347d3d2bbd8e7ce0b63071c52e25"},
+ {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b69a58a37dab856491bf2d3bbf259775fdce262b727f96aafbda359cb1d114d8"},
+ {file = "orjson-3.10.3-cp39-none-win32.whl", hash = "sha256:b8d4d1a6868cde356f1402c8faeb50d62cee765a1f7ffcfd6de732ab0581e063"},
+ {file = "orjson-3.10.3-cp39-none-win_amd64.whl", hash = "sha256:5102f50c5fc46d94f2033fe00d392588564378260d64377aec702f21a7a22912"},
+ {file = "orjson-3.10.3.tar.gz", hash = "sha256:2b166507acae7ba2f7c315dcf185a9111ad5e992ac81f2d507aac39193c2c818"},
]
[[package]]
@@ -2037,12 +2144,13 @@ files = [
[[package]]
name = "parsimonious"
-version = "0.9.0"
+version = "0.10.0"
description = "(Soon to be) the fastest pure-Python PEG parser I could muster"
optional = false
python-versions = "*"
files = [
- {file = "parsimonious-0.9.0.tar.gz", hash = "sha256:b2ad1ae63a2f65bd78f5e0a8ac510a98f3607a43f1db2a8d46636a5d9e4a30c1"},
+ {file = "parsimonious-0.10.0-py3-none-any.whl", hash = "sha256:982ab435fabe86519b57f6b35610aa4e4e977e9f02a14353edf4bbc75369fc0f"},
+ {file = "parsimonious-0.10.0.tar.gz", hash = "sha256:8281600da180ec8ae35427a4ab4f7b82bfec1e3d1e52f80cb60ea82b9512501c"},
]
[package.dependencies]
@@ -2061,28 +2169,29 @@ files = [
[[package]]
name = "platformdirs"
-version = "4.2.0"
-description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+version = "4.2.2"
+description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`."
optional = false
python-versions = ">=3.8"
files = [
- {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"},
- {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"},
+ {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"},
+ {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"},
]
[package.extras]
docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"]
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"]
+type = ["mypy (>=1.8)"]
[[package]]
name = "pluggy"
-version = "1.4.0"
+version = "1.5.0"
description = "plugin and hook calling mechanisms for python"
optional = false
python-versions = ">=3.8"
files = [
- {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"},
- {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"},
+ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"},
+ {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"},
]
[package.extras]
@@ -2091,13 +2200,13 @@ testing = ["pytest", "pytest-benchmark"]
[[package]]
name = "pre-commit"
-version = "3.6.2"
+version = "3.7.1"
description = "A framework for managing and maintaining multi-language pre-commit hooks."
optional = false
python-versions = ">=3.9"
files = [
- {file = "pre_commit-3.6.2-py2.py3-none-any.whl", hash = "sha256:ba637c2d7a670c10daedc059f5c49b5bd0aadbccfcd7ec15592cf9665117532c"},
- {file = "pre_commit-3.6.2.tar.gz", hash = "sha256:c3ef34f463045c88658c5b99f38c1e297abdcc0ff13f98d3370055fbbfabc67e"},
+ {file = "pre_commit-3.7.1-py2.py3-none-any.whl", hash = "sha256:fae36fd1d7ad7d6a5a1c0b0d5adb2ed1a3bda5a21bf6c3e5372073d7a11cd4c5"},
+ {file = "pre_commit-3.7.1.tar.gz", hash = "sha256:8ca3ad567bc78a4972a3f1a477e94a79d4597e8140a6e0b651c5e33899c3654a"},
]
[package.dependencies]
@@ -2107,45 +2216,25 @@ nodeenv = ">=0.11.1"
pyyaml = ">=5.1"
virtualenv = ">=20.10.0"
-[[package]]
-name = "protobuf"
-version = "4.25.3"
-description = ""
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "protobuf-4.25.3-cp310-abi3-win32.whl", hash = "sha256:d4198877797a83cbfe9bffa3803602bbe1625dc30d8a097365dbc762e5790faa"},
- {file = "protobuf-4.25.3-cp310-abi3-win_amd64.whl", hash = "sha256:209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8"},
- {file = "protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c"},
- {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019"},
- {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d"},
- {file = "protobuf-4.25.3-cp38-cp38-win32.whl", hash = "sha256:f4f118245c4a087776e0a8408be33cf09f6c547442c00395fbfb116fac2f8ac2"},
- {file = "protobuf-4.25.3-cp38-cp38-win_amd64.whl", hash = "sha256:c053062984e61144385022e53678fbded7aea14ebb3e0305ae3592fb219ccfa4"},
- {file = "protobuf-4.25.3-cp39-cp39-win32.whl", hash = "sha256:19b270aeaa0099f16d3ca02628546b8baefe2955bbe23224aaf856134eccf1e4"},
- {file = "protobuf-4.25.3-cp39-cp39-win_amd64.whl", hash = "sha256:e3c97a1555fd6388f857770ff8b9703083de6bf1f9274a002a332d65fbb56c8c"},
- {file = "protobuf-4.25.3-py3-none-any.whl", hash = "sha256:f0700d54bcf45424477e46a9f0944155b46fb0639d69728739c0e47bab83f2b9"},
- {file = "protobuf-4.25.3.tar.gz", hash = "sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c"},
-]
-
[[package]]
name = "psycopg"
-version = "3.1.18"
+version = "3.1.19"
description = "PostgreSQL database adapter for Python"
optional = false
python-versions = ">=3.7"
files = [
- {file = "psycopg-3.1.18-py3-none-any.whl", hash = "sha256:4d5a0a5a8590906daa58ebd5f3cfc34091377354a1acced269dd10faf55da60e"},
- {file = "psycopg-3.1.18.tar.gz", hash = "sha256:31144d3fb4c17d78094d9e579826f047d4af1da6a10427d91dfcfb6ecdf6f12b"},
+ {file = "psycopg-3.1.19-py3-none-any.whl", hash = "sha256:dca5e5521c859f6606686432ae1c94e8766d29cc91f2ee595378c510cc5b0731"},
+ {file = "psycopg-3.1.19.tar.gz", hash = "sha256:92d7b78ad82426cdcf1a0440678209faa890c6e1721361c2f8901f0dccd62961"},
]
[package.dependencies]
-psycopg-c = {version = "3.1.18", optional = true, markers = "implementation_name != \"pypy\" and extra == \"c\""}
+psycopg-c = {version = "3.1.19", optional = true, markers = "implementation_name != \"pypy\" and extra == \"c\""}
typing-extensions = ">=4.1"
tzdata = {version = "*", markers = "sys_platform == \"win32\""}
[package.extras]
-binary = ["psycopg-binary (==3.1.18)"]
-c = ["psycopg-c (==3.1.18)"]
+binary = ["psycopg-binary (==3.1.19)"]
+c = ["psycopg-c (==3.1.19)"]
dev = ["black (>=24.1.0)", "codespell (>=2.2)", "dnspython (>=2.1)", "flake8 (>=4.0)", "mypy (>=1.4.1)", "types-setuptools (>=57.4)", "wheel (>=0.37)"]
docs = ["Sphinx (>=5.0)", "furo (==2022.6.21)", "sphinx-autobuild (>=2021.3.14)", "sphinx-autodoc-typehints (>=1.12)"]
pool = ["psycopg-pool"]
@@ -2153,23 +2242,23 @@ test = ["anyio (>=3.6.2,<4.0)", "mypy (>=1.4.1)", "pproxy (>=2.7)", "pytest (>=6
[[package]]
name = "psycopg-c"
-version = "3.1.18"
+version = "3.1.19"
description = "PostgreSQL database adapter for Python -- C optimisation distribution"
optional = false
python-versions = ">=3.7"
files = [
- {file = "psycopg-c-3.1.18.tar.gz", hash = "sha256:ffff0c4a9c0e0b7aadb1acb7b61eb8f886365dd8ef00120ce14676235846ba73"},
+ {file = "psycopg_c-3.1.19.tar.gz", hash = "sha256:8e90f53c430e7d661cb3a9298e2761847212ead1b24c5fb058fc9d0fd9616017"},
]
[[package]]
name = "pycparser"
-version = "2.21"
+version = "2.22"
description = "C parser in Python"
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+python-versions = ">=3.8"
files = [
- {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
- {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
+ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"},
+ {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"},
]
[[package]]
@@ -2215,18 +2304,18 @@ files = [
[[package]]
name = "pydantic"
-version = "2.6.3"
+version = "2.7.2"
description = "Data validation using Python type hints"
optional = false
python-versions = ">=3.8"
files = [
- {file = "pydantic-2.6.3-py3-none-any.whl", hash = "sha256:72c6034df47f46ccdf81869fddb81aade68056003900a8724a4f160700016a2a"},
- {file = "pydantic-2.6.3.tar.gz", hash = "sha256:e07805c4c7f5c6826e33a1d4c9d47950d7eaf34868e2690f8594d2e30241f11f"},
+ {file = "pydantic-2.7.2-py3-none-any.whl", hash = "sha256:834ab954175f94e6e68258537dc49402c4a5e9d0409b9f1b86b7e934a8372de7"},
+ {file = "pydantic-2.7.2.tar.gz", hash = "sha256:71b2945998f9c9b7919a45bde9a50397b289937d215ae141c1d0903ba7149fd7"},
]
[package.dependencies]
annotated-types = ">=0.4.0"
-pydantic-core = "2.16.3"
+pydantic-core = "2.18.3"
typing-extensions = ">=4.6.1"
[package.extras]
@@ -2234,90 +2323,90 @@ email = ["email-validator (>=2.0.0)"]
[[package]]
name = "pydantic-core"
-version = "2.16.3"
-description = ""
+version = "2.18.3"
+description = "Core functionality for Pydantic validation and serialization"
optional = false
python-versions = ">=3.8"
files = [
- {file = "pydantic_core-2.16.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:75b81e678d1c1ede0785c7f46690621e4c6e63ccd9192af1f0bd9d504bbb6bf4"},
- {file = "pydantic_core-2.16.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9c865a7ee6f93783bd5d781af5a4c43dadc37053a5b42f7d18dc019f8c9d2bd1"},
- {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:162e498303d2b1c036b957a1278fa0899d02b2842f1ff901b6395104c5554a45"},
- {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f583bd01bbfbff4eaee0868e6fc607efdfcc2b03c1c766b06a707abbc856187"},
- {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b926dd38db1519ed3043a4de50214e0d600d404099c3392f098a7f9d75029ff8"},
- {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:716b542728d4c742353448765aa7cdaa519a7b82f9564130e2b3f6766018c9ec"},
- {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4ad7f7ee1a13d9cb49d8198cd7d7e3aa93e425f371a68235f784e99741561f"},
- {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd87f48924f360e5d1c5f770d6155ce0e7d83f7b4e10c2f9ec001c73cf475c99"},
- {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0df446663464884297c793874573549229f9eca73b59360878f382a0fc085979"},
- {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4df8a199d9f6afc5ae9a65f8f95ee52cae389a8c6b20163762bde0426275b7db"},
- {file = "pydantic_core-2.16.3-cp310-none-win32.whl", hash = "sha256:456855f57b413f077dff513a5a28ed838dbbb15082ba00f80750377eed23d132"},
- {file = "pydantic_core-2.16.3-cp310-none-win_amd64.whl", hash = "sha256:732da3243e1b8d3eab8c6ae23ae6a58548849d2e4a4e03a1924c8ddf71a387cb"},
- {file = "pydantic_core-2.16.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:519ae0312616026bf4cedc0fe459e982734f3ca82ee8c7246c19b650b60a5ee4"},
- {file = "pydantic_core-2.16.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b3992a322a5617ded0a9f23fd06dbc1e4bd7cf39bc4ccf344b10f80af58beacd"},
- {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d62da299c6ecb04df729e4b5c52dc0d53f4f8430b4492b93aa8de1f541c4aac"},
- {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2acca2be4bb2f2147ada8cac612f8a98fc09f41c89f87add7256ad27332c2fda"},
- {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b662180108c55dfbf1280d865b2d116633d436cfc0bba82323554873967b340"},
- {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7c6ed0dc9d8e65f24f5824291550139fe6f37fac03788d4580da0d33bc00c97"},
- {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1bb0827f56654b4437955555dc3aeeebeddc47c2d7ed575477f082622c49e"},
- {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e56f8186d6210ac7ece503193ec84104da7ceb98f68ce18c07282fcc2452e76f"},
- {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:936e5db01dd49476fa8f4383c259b8b1303d5dd5fb34c97de194560698cc2c5e"},
- {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33809aebac276089b78db106ee692bdc9044710e26f24a9a2eaa35a0f9fa70ba"},
- {file = "pydantic_core-2.16.3-cp311-none-win32.whl", hash = "sha256:ded1c35f15c9dea16ead9bffcde9bb5c7c031bff076355dc58dcb1cb436c4721"},
- {file = "pydantic_core-2.16.3-cp311-none-win_amd64.whl", hash = "sha256:d89ca19cdd0dd5f31606a9329e309d4fcbb3df860960acec32630297d61820df"},
- {file = "pydantic_core-2.16.3-cp311-none-win_arm64.whl", hash = "sha256:6162f8d2dc27ba21027f261e4fa26f8bcb3cf9784b7f9499466a311ac284b5b9"},
- {file = "pydantic_core-2.16.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f56ae86b60ea987ae8bcd6654a887238fd53d1384f9b222ac457070b7ac4cff"},
- {file = "pydantic_core-2.16.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9bd22a2a639e26171068f8ebb5400ce2c1bc7d17959f60a3b753ae13c632975"},
- {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4204e773b4b408062960e65468d5346bdfe139247ee5f1ca2a378983e11388a2"},
- {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f651dd19363c632f4abe3480a7c87a9773be27cfe1341aef06e8759599454120"},
- {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaf09e615a0bf98d406657e0008e4a8701b11481840be7d31755dc9f97c44053"},
- {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8e47755d8152c1ab5b55928ab422a76e2e7b22b5ed8e90a7d584268dd49e9c6b"},
- {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:500960cb3a0543a724a81ba859da816e8cf01b0e6aaeedf2c3775d12ee49cade"},
- {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf6204fe865da605285c34cf1172879d0314ff267b1c35ff59de7154f35fdc2e"},
- {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d33dd21f572545649f90c38c227cc8631268ba25c460b5569abebdd0ec5974ca"},
- {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:49d5d58abd4b83fb8ce763be7794d09b2f50f10aa65c0f0c1696c677edeb7cbf"},
- {file = "pydantic_core-2.16.3-cp312-none-win32.whl", hash = "sha256:f53aace168a2a10582e570b7736cc5bef12cae9cf21775e3eafac597e8551fbe"},
- {file = "pydantic_core-2.16.3-cp312-none-win_amd64.whl", hash = "sha256:0d32576b1de5a30d9a97f300cc6a3f4694c428d956adbc7e6e2f9cad279e45ed"},
- {file = "pydantic_core-2.16.3-cp312-none-win_arm64.whl", hash = "sha256:ec08be75bb268473677edb83ba71e7e74b43c008e4a7b1907c6d57e940bf34b6"},
- {file = "pydantic_core-2.16.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b1f6f5938d63c6139860f044e2538baeee6f0b251a1816e7adb6cbce106a1f01"},
- {file = "pydantic_core-2.16.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2a1ef6a36fdbf71538142ed604ad19b82f67b05749512e47f247a6ddd06afdc7"},
- {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:704d35ecc7e9c31d48926150afada60401c55efa3b46cd1ded5a01bdffaf1d48"},
- {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d937653a696465677ed583124b94a4b2d79f5e30b2c46115a68e482c6a591c8a"},
- {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9803edf8e29bd825f43481f19c37f50d2b01899448273b3a7758441b512acf8"},
- {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72282ad4892a9fb2da25defeac8c2e84352c108705c972db82ab121d15f14e6d"},
- {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f752826b5b8361193df55afcdf8ca6a57d0232653494ba473630a83ba50d8c9"},
- {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4384a8f68ddb31a0b0c3deae88765f5868a1b9148939c3f4121233314ad5532c"},
- {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4b2bf78342c40b3dc830880106f54328928ff03e357935ad26c7128bbd66ce8"},
- {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:13dcc4802961b5f843a9385fc821a0b0135e8c07fc3d9949fd49627c1a5e6ae5"},
- {file = "pydantic_core-2.16.3-cp38-none-win32.whl", hash = "sha256:e3e70c94a0c3841e6aa831edab1619ad5c511199be94d0c11ba75fe06efe107a"},
- {file = "pydantic_core-2.16.3-cp38-none-win_amd64.whl", hash = "sha256:ecdf6bf5f578615f2e985a5e1f6572e23aa632c4bd1dc67f8f406d445ac115ed"},
- {file = "pydantic_core-2.16.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:bda1ee3e08252b8d41fa5537413ffdddd58fa73107171a126d3b9ff001b9b820"},
- {file = "pydantic_core-2.16.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:21b888c973e4f26b7a96491c0965a8a312e13be108022ee510248fe379a5fa23"},
- {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be0ec334369316fa73448cc8c982c01e5d2a81c95969d58b8f6e272884df0074"},
- {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5b6079cc452a7c53dd378c6f881ac528246b3ac9aae0f8eef98498a75657805"},
- {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee8d5f878dccb6d499ba4d30d757111847b6849ae07acdd1205fffa1fc1253c"},
- {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7233d65d9d651242a68801159763d09e9ec96e8a158dbf118dc090cd77a104c9"},
- {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6119dc90483a5cb50a1306adb8d52c66e447da88ea44f323e0ae1a5fcb14256"},
- {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:578114bc803a4c1ff9946d977c221e4376620a46cf78da267d946397dc9514a8"},
- {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d8f99b147ff3fcf6b3cc60cb0c39ea443884d5559a30b1481e92495f2310ff2b"},
- {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4ac6b4ce1e7283d715c4b729d8f9dab9627586dafce81d9eaa009dd7f25dd972"},
- {file = "pydantic_core-2.16.3-cp39-none-win32.whl", hash = "sha256:e7774b570e61cb998490c5235740d475413a1f6de823169b4cf94e2fe9e9f6b2"},
- {file = "pydantic_core-2.16.3-cp39-none-win_amd64.whl", hash = "sha256:9091632a25b8b87b9a605ec0e61f241c456e9248bfdcf7abdf344fdb169c81cf"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:36fa178aacbc277bc6b62a2c3da95226520da4f4e9e206fdf076484363895d2c"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:dcca5d2bf65c6fb591fff92da03f94cd4f315972f97c21975398bd4bd046854a"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a72fb9963cba4cd5793854fd12f4cfee731e86df140f59ff52a49b3552db241"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60cc1a081f80a2105a59385b92d82278b15d80ebb3adb200542ae165cd7d183"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cbcc558401de90a746d02ef330c528f2e668c83350f045833543cd57ecead1ad"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fee427241c2d9fb7192b658190f9f5fd6dfe41e02f3c1489d2ec1e6a5ab1e04a"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f4cb85f693044e0f71f394ff76c98ddc1bc0953e48c061725e540396d5c8a2e1"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b29eeb887aa931c2fcef5aa515d9d176d25006794610c264ddc114c053bf96fe"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a425479ee40ff021f8216c9d07a6a3b54b31c8267c6e17aa88b70d7ebd0e5e5b"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5c5cbc703168d1b7a838668998308018a2718c2130595e8e190220238addc96f"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99b6add4c0b39a513d323d3b93bc173dac663c27b99860dd5bf491b240d26137"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f76ee558751746d6a38f89d60b6228fa174e5172d143886af0f85aa306fd89"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00ee1c97b5364b84cb0bd82e9bbf645d5e2871fb8c58059d158412fee2d33d8a"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:287073c66748f624be4cef893ef9174e3eb88fe0b8a78dc22e88eca4bc357ca6"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed25e1835c00a332cb10c683cd39da96a719ab1dfc08427d476bce41b92531fc"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:86b3d0033580bd6bbe07590152007275bd7af95f98eaa5bd36f3da219dcd93da"},
- {file = "pydantic_core-2.16.3.tar.gz", hash = "sha256:1cac689f80a3abab2d3c0048b29eea5751114054f032a941a32de4c852c59cad"},
+ {file = "pydantic_core-2.18.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:744697428fcdec6be5670460b578161d1ffe34743a5c15656be7ea82b008197c"},
+ {file = "pydantic_core-2.18.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37b40c05ced1ba4218b14986fe6f283d22e1ae2ff4c8e28881a70fb81fbfcda7"},
+ {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a9a75622357076efb6b311983ff190fbfb3c12fc3a853122b34d3d358126c"},
+ {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e2e253af04ceaebde8eb201eb3f3e3e7e390f2d275a88300d6a1959d710539e2"},
+ {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:855ec66589c68aa367d989da5c4755bb74ee92ccad4fdb6af942c3612c067e34"},
+ {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d3e42bb54e7e9d72c13ce112e02eb1b3b55681ee948d748842171201a03a98a"},
+ {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6ac9ffccc9d2e69d9fba841441d4259cb668ac180e51b30d3632cd7abca2b9b"},
+ {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c56eca1686539fa0c9bda992e7bd6a37583f20083c37590413381acfc5f192d6"},
+ {file = "pydantic_core-2.18.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:17954d784bf8abfc0ec2a633108207ebc4fa2df1a0e4c0c3ccbaa9bb01d2c426"},
+ {file = "pydantic_core-2.18.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:98ed737567d8f2ecd54f7c8d4f8572ca7c7921ede93a2e52939416170d357812"},
+ {file = "pydantic_core-2.18.3-cp310-none-win32.whl", hash = "sha256:9f9e04afebd3ed8c15d67a564ed0a34b54e52136c6d40d14c5547b238390e779"},
+ {file = "pydantic_core-2.18.3-cp310-none-win_amd64.whl", hash = "sha256:45e4ffbae34f7ae30d0047697e724e534a7ec0a82ef9994b7913a412c21462a0"},
+ {file = "pydantic_core-2.18.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b9ebe8231726c49518b16b237b9fe0d7d361dd221302af511a83d4ada01183ab"},
+ {file = "pydantic_core-2.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b8e20e15d18bf7dbb453be78a2d858f946f5cdf06c5072453dace00ab652e2b2"},
+ {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0d9ff283cd3459fa0bf9b0256a2b6f01ac1ff9ffb034e24457b9035f75587cb"},
+ {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f7ef5f0ebb77ba24c9970da18b771711edc5feaf00c10b18461e0f5f5949231"},
+ {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73038d66614d2e5cde30435b5afdced2b473b4c77d4ca3a8624dd3e41a9c19be"},
+ {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6afd5c867a74c4d314c557b5ea9520183fadfbd1df4c2d6e09fd0d990ce412cd"},
+ {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd7df92f28d351bb9f12470f4c533cf03d1b52ec5a6e5c58c65b183055a60106"},
+ {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:80aea0ffeb1049336043d07799eace1c9602519fb3192916ff525b0287b2b1e4"},
+ {file = "pydantic_core-2.18.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaee40f25bba38132e655ffa3d1998a6d576ba7cf81deff8bfa189fb43fd2bbe"},
+ {file = "pydantic_core-2.18.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9128089da8f4fe73f7a91973895ebf2502539d627891a14034e45fb9e707e26d"},
+ {file = "pydantic_core-2.18.3-cp311-none-win32.whl", hash = "sha256:fec02527e1e03257aa25b1a4dcbe697b40a22f1229f5d026503e8b7ff6d2eda7"},
+ {file = "pydantic_core-2.18.3-cp311-none-win_amd64.whl", hash = "sha256:58ff8631dbab6c7c982e6425da8347108449321f61fe427c52ddfadd66642af7"},
+ {file = "pydantic_core-2.18.3-cp311-none-win_arm64.whl", hash = "sha256:3fc1c7f67f34c6c2ef9c213e0f2a351797cda98249d9ca56a70ce4ebcaba45f4"},
+ {file = "pydantic_core-2.18.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f0928cde2ae416a2d1ebe6dee324709c6f73e93494d8c7aea92df99aab1fc40f"},
+ {file = "pydantic_core-2.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0bee9bb305a562f8b9271855afb6ce00223f545de3d68560b3c1649c7c5295e9"},
+ {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e862823be114387257dacbfa7d78547165a85d7add33b446ca4f4fae92c7ff5c"},
+ {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a36f78674cbddc165abab0df961b5f96b14461d05feec5e1f78da58808b97e7"},
+ {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba905d184f62e7ddbb7a5a751d8a5c805463511c7b08d1aca4a3e8c11f2e5048"},
+ {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fdd362f6a586e681ff86550b2379e532fee63c52def1c666887956748eaa326"},
+ {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24b214b7ee3bd3b865e963dbed0f8bc5375f49449d70e8d407b567af3222aae4"},
+ {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:691018785779766127f531674fa82bb368df5b36b461622b12e176c18e119022"},
+ {file = "pydantic_core-2.18.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:60e4c625e6f7155d7d0dcac151edf5858102bc61bf959d04469ca6ee4e8381bd"},
+ {file = "pydantic_core-2.18.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4e651e47d981c1b701dcc74ab8fec5a60a5b004650416b4abbef13db23bc7be"},
+ {file = "pydantic_core-2.18.3-cp312-none-win32.whl", hash = "sha256:ffecbb5edb7f5ffae13599aec33b735e9e4c7676ca1633c60f2c606beb17efc5"},
+ {file = "pydantic_core-2.18.3-cp312-none-win_amd64.whl", hash = "sha256:2c8333f6e934733483c7eddffdb094c143b9463d2af7e6bd85ebcb2d4a1b82c6"},
+ {file = "pydantic_core-2.18.3-cp312-none-win_arm64.whl", hash = "sha256:7a20dded653e516a4655f4c98e97ccafb13753987434fe7cf044aa25f5b7d417"},
+ {file = "pydantic_core-2.18.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:eecf63195be644b0396f972c82598cd15693550f0ff236dcf7ab92e2eb6d3522"},
+ {file = "pydantic_core-2.18.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c44efdd3b6125419c28821590d7ec891c9cb0dff33a7a78d9d5c8b6f66b9702"},
+ {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e59fca51ffbdd1638b3856779342ed69bcecb8484c1d4b8bdb237d0eb5a45e2"},
+ {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:70cf099197d6b98953468461d753563b28e73cf1eade2ffe069675d2657ed1d5"},
+ {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63081a49dddc6124754b32a3774331467bfc3d2bd5ff8f10df36a95602560361"},
+ {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:370059b7883485c9edb9655355ff46d912f4b03b009d929220d9294c7fd9fd60"},
+ {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a64faeedfd8254f05f5cf6fc755023a7e1606af3959cfc1a9285744cc711044"},
+ {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19d2e725de0f90d8671f89e420d36c3dd97639b98145e42fcc0e1f6d492a46dc"},
+ {file = "pydantic_core-2.18.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:67bc078025d70ec5aefe6200ef094576c9d86bd36982df1301c758a9fff7d7f4"},
+ {file = "pydantic_core-2.18.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:adf952c3f4100e203cbaf8e0c907c835d3e28f9041474e52b651761dc248a3c0"},
+ {file = "pydantic_core-2.18.3-cp38-none-win32.whl", hash = "sha256:9a46795b1f3beb167eaee91736d5d17ac3a994bf2215a996aed825a45f897558"},
+ {file = "pydantic_core-2.18.3-cp38-none-win_amd64.whl", hash = "sha256:200ad4e3133cb99ed82342a101a5abf3d924722e71cd581cc113fe828f727fbc"},
+ {file = "pydantic_core-2.18.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:304378b7bf92206036c8ddd83a2ba7b7d1a5b425acafff637172a3aa72ad7083"},
+ {file = "pydantic_core-2.18.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c826870b277143e701c9ccf34ebc33ddb4d072612683a044e7cce2d52f6c3fef"},
+ {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e201935d282707394f3668380e41ccf25b5794d1b131cdd96b07f615a33ca4b1"},
+ {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5560dda746c44b48bf82b3d191d74fe8efc5686a9ef18e69bdabccbbb9ad9442"},
+ {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b32c2a1f8032570842257e4c19288eba9a2bba4712af542327de9a1204faff8"},
+ {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:929c24e9dea3990bc8bcd27c5f2d3916c0c86f5511d2caa69e0d5290115344a9"},
+ {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a8376fef60790152564b0eab376b3e23dd6e54f29d84aad46f7b264ecca943"},
+ {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dccf3ef1400390ddd1fb55bf0632209d39140552d068ee5ac45553b556780e06"},
+ {file = "pydantic_core-2.18.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:41dbdcb0c7252b58fa931fec47937edb422c9cb22528f41cb8963665c372caf6"},
+ {file = "pydantic_core-2.18.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:666e45cf071669fde468886654742fa10b0e74cd0fa0430a46ba6056b24fb0af"},
+ {file = "pydantic_core-2.18.3-cp39-none-win32.whl", hash = "sha256:f9c08cabff68704a1b4667d33f534d544b8a07b8e5d039c37067fceb18789e78"},
+ {file = "pydantic_core-2.18.3-cp39-none-win_amd64.whl", hash = "sha256:4afa5f5973e8572b5c0dcb4e2d4fda7890e7cd63329bd5cc3263a25c92ef0026"},
+ {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:77319771a026f7c7d29c6ebc623de889e9563b7087911b46fd06c044a12aa5e9"},
+ {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:df11fa992e9f576473038510d66dd305bcd51d7dd508c163a8c8fe148454e059"},
+ {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d531076bdfb65af593326ffd567e6ab3da145020dafb9187a1d131064a55f97c"},
+ {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d33ce258e4e6e6038f2b9e8b8a631d17d017567db43483314993b3ca345dcbbb"},
+ {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1f9cd7f5635b719939019be9bda47ecb56e165e51dd26c9a217a433e3d0d59a9"},
+ {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cd4a032bb65cc132cae1fe3e52877daecc2097965cd3914e44fbd12b00dae7c5"},
+ {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f2718430098bcdf60402136c845e4126a189959d103900ebabb6774a5d9fdb"},
+ {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c0037a92cf0c580ed14e10953cdd26528e8796307bb8bb312dc65f71547df04d"},
+ {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b95a0972fac2b1ff3c94629fc9081b16371dad870959f1408cc33b2f78ad347a"},
+ {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a62e437d687cc148381bdd5f51e3e81f5b20a735c55f690c5be94e05da2b0d5c"},
+ {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b367a73a414bbb08507da102dc2cde0fa7afe57d09b3240ce82a16d608a7679c"},
+ {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ecce4b2360aa3f008da3327d652e74a0e743908eac306198b47e1c58b03dd2b"},
+ {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd4435b8d83f0c9561a2a9585b1de78f1abb17cb0cef5f39bf6a4b47d19bafe3"},
+ {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:616221a6d473c5b9aa83fa8982745441f6a4a62a66436be9445c65f241b86c94"},
+ {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:7e6382ce89a92bc1d0c0c5edd51e931432202b9080dc921d8d003e616402efd1"},
+ {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ff58f379345603d940e461eae474b6bbb6dab66ed9a851ecd3cb3709bf4dcf6a"},
+ {file = "pydantic_core-2.18.3.tar.gz", hash = "sha256:432e999088d85c8f36b9a3f769a8e2b57aabd817bbb729a90d1fe7f18f6f1f39"},
]
[package.dependencies]
@@ -2325,17 +2414,16 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
[[package]]
name = "pygments"
-version = "2.17.2"
+version = "2.18.0"
description = "Pygments is a syntax highlighting package written in Python."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"},
- {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"},
+ {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"},
+ {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"},
]
[package.extras]
-plugins = ["importlib-metadata"]
windows-terminal = ["colorama (>=0.4.6)"]
[[package]]
@@ -2444,6 +2532,26 @@ files = [
freezegun = ">=1.0"
pytest = ">=3.6"
+[[package]]
+name = "pytest-memray"
+version = "1.6.0"
+description = "A simple plugin to use with pytest"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pytest_memray-1.6.0-py3-none-any.whl", hash = "sha256:267db3f9d3ad3e443c6743e5261ce64caff3e2e8d632850b58c0ae0925fed765"},
+ {file = "pytest_memray-1.6.0.tar.gz", hash = "sha256:364152252afd563fc8b58459325f360030d2b0d5673896018a68badb35402339"},
+]
+
+[package.dependencies]
+memray = ">=1.12"
+pytest = ">=7.2"
+
+[package.extras]
+docs = ["furo (>=2022.12.7)", "sphinx (>=6.1.3)", "sphinx-argparse (>=0.4)", "sphinx-inline-tabs (>=2022.1.2b11)", "sphinxcontrib-programoutput (>=0.17)", "towncrier (>=22.12)"]
+lint = ["black (==22.12)", "isort (==5.11.4)", "mypy (==0.991)", "ruff (==0.0.272)"]
+test = ["covdefaults (>=2.2.2)", "coverage (>=7.0.5)", "flaky (>=3.7)", "pytest (>=7.2)", "pytest-xdist (>=3.1)"]
+
[[package]]
name = "python-dateutil"
version = "2.9.0.post0"
@@ -2472,6 +2580,20 @@ files = [
[package.extras]
cli = ["click (>=5.0)"]
+[[package]]
+name = "python-multipart"
+version = "0.0.9"
+description = "A streaming multipart parser for Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "python_multipart-0.0.9-py3-none-any.whl", hash = "sha256:97ca7b8ea7b05f977dc3849c3ba99d51689822fab725c3703af7c866a0c2b215"},
+ {file = "python_multipart-0.0.9.tar.gz", hash = "sha256:03f54688c663f1b7977105f021043b0793151e4cb1c1a9d4a11fc13d622c4026"},
+]
+
+[package.extras]
+dev = ["atomicwrites (==1.4.1)", "attrs (==23.2.0)", "coverage (==7.4.1)", "hatch", "invoke (==2.2.0)", "more-itertools (==10.2.0)", "pbr (==6.0.0)", "pluggy (==1.4.0)", "py (==1.11.0)", "pytest (==8.0.0)", "pytest-cov (==4.1.0)", "pytest-timeout (==2.2.0)", "pyyaml (==6.0.1)", "ruff (==0.2.1)"]
+
[[package]]
name = "pytz"
version = "2024.1"
@@ -2565,132 +2687,103 @@ files = [
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
]
-[[package]]
-name = "referencing"
-version = "0.33.0"
-description = "JSON Referencing + Python"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "referencing-0.33.0-py3-none-any.whl", hash = "sha256:39240f2ecc770258f28b642dd47fd74bc8b02484de54e1882b74b35ebd779bd5"},
- {file = "referencing-0.33.0.tar.gz", hash = "sha256:c775fedf74bc0f9189c2a3be1c12fd03e8c23f4d371dce795df44e06c5b412f7"},
-]
-
-[package.dependencies]
-attrs = ">=22.2.0"
-rpds-py = ">=0.7.0"
-
[[package]]
name = "regex"
-version = "2023.12.25"
+version = "2024.5.15"
description = "Alternative regular expression module, to replace re."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5"},
- {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8"},
- {file = "regex-2023.12.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586"},
- {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c"},
- {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400"},
- {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e"},
- {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4"},
- {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5"},
- {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd"},
- {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704"},
- {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1"},
- {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392"},
- {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423"},
- {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f"},
- {file = "regex-2023.12.25-cp310-cp310-win32.whl", hash = "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630"},
- {file = "regex-2023.12.25-cp310-cp310-win_amd64.whl", hash = "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105"},
- {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6"},
- {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97"},
- {file = "regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887"},
- {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb"},
- {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c"},
- {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b"},
- {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa"},
- {file = "regex-2023.12.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7"},
- {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0"},
- {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe"},
- {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80"},
- {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd"},
- {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4"},
- {file = "regex-2023.12.25-cp311-cp311-win32.whl", hash = "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87"},
- {file = "regex-2023.12.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f"},
- {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715"},
- {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d"},
- {file = "regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a"},
- {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7a635871143661feccce3979e1727c4e094f2bdfd3ec4b90dfd4f16f571a87a"},
- {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d498eea3f581fbe1b34b59c697512a8baef88212f92e4c7830fcc1499f5b45a5"},
- {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43f7cd5754d02a56ae4ebb91b33461dc67be8e3e0153f593c509e21d219c5060"},
- {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51f4b32f793812714fd5307222a7f77e739b9bc566dc94a18126aba3b92b98a3"},
- {file = "regex-2023.12.25-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba99d8077424501b9616b43a2d208095746fb1284fc5ba490139651f971d39d9"},
- {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4bfc2b16e3ba8850e0e262467275dd4d62f0d045e0e9eda2bc65078c0110a11f"},
- {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8c2c19dae8a3eb0ea45a8448356ed561be843b13cbc34b840922ddf565498c1c"},
- {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:60080bb3d8617d96f0fb7e19796384cc2467447ef1c491694850ebd3670bc457"},
- {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b77e27b79448e34c2c51c09836033056a0547aa360c45eeeb67803da7b0eedaf"},
- {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:518440c991f514331f4850a63560321f833979d145d7d81186dbe2f19e27ae3d"},
- {file = "regex-2023.12.25-cp312-cp312-win32.whl", hash = "sha256:e2610e9406d3b0073636a3a2e80db05a02f0c3169b5632022b4e81c0364bcda5"},
- {file = "regex-2023.12.25-cp312-cp312-win_amd64.whl", hash = "sha256:cc37b9aeebab425f11f27e5e9e6cf580be7206c6582a64467a14dda211abc232"},
- {file = "regex-2023.12.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:da695d75ac97cb1cd725adac136d25ca687da4536154cdc2815f576e4da11c69"},
- {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d126361607b33c4eb7b36debc173bf25d7805847346dd4d99b5499e1fef52bc7"},
- {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4719bb05094d7d8563a450cf8738d2e1061420f79cfcc1fa7f0a44744c4d8f73"},
- {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dd58946bce44b53b06d94aa95560d0b243eb2fe64227cba50017a8d8b3cd3e2"},
- {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22a86d9fff2009302c440b9d799ef2fe322416d2d58fc124b926aa89365ec482"},
- {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2aae8101919e8aa05ecfe6322b278f41ce2994c4a430303c4cd163fef746e04f"},
- {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e692296c4cc2873967771345a876bcfc1c547e8dd695c6b89342488b0ea55cd8"},
- {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:263ef5cc10979837f243950637fffb06e8daed7f1ac1e39d5910fd29929e489a"},
- {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d6f7e255e5fa94642a0724e35406e6cb7001c09d476ab5fce002f652b36d0c39"},
- {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:88ad44e220e22b63b0f8f81f007e8abbb92874d8ced66f32571ef8beb0643b2b"},
- {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3a17d3ede18f9cedcbe23d2daa8a2cd6f59fe2bf082c567e43083bba3fb00347"},
- {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d15b274f9e15b1a0b7a45d2ac86d1f634d983ca40d6b886721626c47a400bf39"},
- {file = "regex-2023.12.25-cp37-cp37m-win32.whl", hash = "sha256:ed19b3a05ae0c97dd8f75a5d8f21f7723a8c33bbc555da6bbe1f96c470139d3c"},
- {file = "regex-2023.12.25-cp37-cp37m-win_amd64.whl", hash = "sha256:a6d1047952c0b8104a1d371f88f4ab62e6275567d4458c1e26e9627ad489b445"},
- {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b43523d7bc2abd757119dbfb38af91b5735eea45537ec6ec3a5ec3f9562a1c53"},
- {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:efb2d82f33b2212898f1659fb1c2e9ac30493ac41e4d53123da374c3b5541e64"},
- {file = "regex-2023.12.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7fca9205b59c1a3d5031f7e64ed627a1074730a51c2a80e97653e3e9fa0d415"},
- {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086dd15e9435b393ae06f96ab69ab2d333f5d65cbe65ca5a3ef0ec9564dfe770"},
- {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e81469f7d01efed9b53740aedd26085f20d49da65f9c1f41e822a33992cb1590"},
- {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34e4af5b27232f68042aa40a91c3b9bb4da0eeb31b7632e0091afc4310afe6cb"},
- {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9852b76ab558e45b20bf1893b59af64a28bd3820b0c2efc80e0a70a4a3ea51c1"},
- {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff100b203092af77d1a5a7abe085b3506b7eaaf9abf65b73b7d6905b6cb76988"},
- {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cc038b2d8b1470364b1888a98fd22d616fba2b6309c5b5f181ad4483e0017861"},
- {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:094ba386bb5c01e54e14434d4caabf6583334090865b23ef58e0424a6286d3dc"},
- {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5cd05d0f57846d8ba4b71d9c00f6f37d6b97d5e5ef8b3c3840426a475c8f70f4"},
- {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:9aa1a67bbf0f957bbe096375887b2505f5d8ae16bf04488e8b0f334c36e31360"},
- {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:98a2636994f943b871786c9e82bfe7883ecdaba2ef5df54e1450fa9869d1f756"},
- {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37f8e93a81fc5e5bd8db7e10e62dc64261bcd88f8d7e6640aaebe9bc180d9ce2"},
- {file = "regex-2023.12.25-cp38-cp38-win32.whl", hash = "sha256:d78bd484930c1da2b9679290a41cdb25cc127d783768a0369d6b449e72f88beb"},
- {file = "regex-2023.12.25-cp38-cp38-win_amd64.whl", hash = "sha256:b521dcecebc5b978b447f0f69b5b7f3840eac454862270406a39837ffae4e697"},
- {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f7bc09bc9c29ebead055bcba136a67378f03d66bf359e87d0f7c759d6d4ffa31"},
- {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e14b73607d6231f3cc4622809c196b540a6a44e903bcfad940779c80dffa7be7"},
- {file = "regex-2023.12.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9eda5f7a50141291beda3edd00abc2d4a5b16c29c92daf8d5bd76934150f3edc"},
- {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc6bb9aa69aacf0f6032c307da718f61a40cf970849e471254e0e91c56ffca95"},
- {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:298dc6354d414bc921581be85695d18912bea163a8b23cac9a2562bbcd5088b1"},
- {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f4e475a80ecbd15896a976aa0b386c5525d0ed34d5c600b6d3ebac0a67c7ddf"},
- {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531ac6cf22b53e0696f8e1d56ce2396311254eb806111ddd3922c9d937151dae"},
- {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22f3470f7524b6da61e2020672df2f3063676aff444db1daa283c2ea4ed259d6"},
- {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:89723d2112697feaa320c9d351e5f5e7b841e83f8b143dba8e2d2b5f04e10923"},
- {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0ecf44ddf9171cd7566ef1768047f6e66975788258b1c6c6ca78098b95cf9a3d"},
- {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:905466ad1702ed4acfd67a902af50b8db1feeb9781436372261808df7a2a7bca"},
- {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:4558410b7a5607a645e9804a3e9dd509af12fb72b9825b13791a37cd417d73a5"},
- {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7e316026cc1095f2a3e8cc012822c99f413b702eaa2ca5408a513609488cb62f"},
- {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b1de218d5375cd6ac4b5493e0b9f3df2be331e86520f23382f216c137913d20"},
- {file = "regex-2023.12.25-cp39-cp39-win32.whl", hash = "sha256:11a963f8e25ab5c61348d090bf1b07f1953929c13bd2309a0662e9ff680763c9"},
- {file = "regex-2023.12.25-cp39-cp39-win_amd64.whl", hash = "sha256:e693e233ac92ba83a87024e1d32b5f9ab15ca55ddd916d878146f4e3406b5c91"},
- {file = "regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5"},
+ {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a81e3cfbae20378d75185171587cbf756015ccb14840702944f014e0d93ea09f"},
+ {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7b59138b219ffa8979013be7bc85bb60c6f7b7575df3d56dc1e403a438c7a3f6"},
+ {file = "regex-2024.5.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0bd000c6e266927cb7a1bc39d55be95c4b4f65c5be53e659537537e019232b1"},
+ {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eaa7ddaf517aa095fa8da0b5015c44d03da83f5bd49c87961e3c997daed0de7"},
+ {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba68168daedb2c0bab7fd7e00ced5ba90aebf91024dea3c88ad5063c2a562cca"},
+ {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e8d717bca3a6e2064fc3a08df5cbe366369f4b052dcd21b7416e6d71620dca1"},
+ {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1337b7dbef9b2f71121cdbf1e97e40de33ff114801263b275aafd75303bd62b5"},
+ {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9ebd0a36102fcad2f03696e8af4ae682793a5d30b46c647eaf280d6cfb32796"},
+ {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9efa1a32ad3a3ea112224897cdaeb6aa00381627f567179c0314f7b65d354c62"},
+ {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1595f2d10dff3d805e054ebdc41c124753631b6a471b976963c7b28543cf13b0"},
+ {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b802512f3e1f480f41ab5f2cfc0e2f761f08a1f41092d6718868082fc0d27143"},
+ {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a0981022dccabca811e8171f913de05720590c915b033b7e601f35ce4ea7019f"},
+ {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:19068a6a79cf99a19ccefa44610491e9ca02c2be3305c7760d3831d38a467a6f"},
+ {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1b5269484f6126eee5e687785e83c6b60aad7663dafe842b34691157e5083e53"},
+ {file = "regex-2024.5.15-cp310-cp310-win32.whl", hash = "sha256:ada150c5adfa8fbcbf321c30c751dc67d2f12f15bd183ffe4ec7cde351d945b3"},
+ {file = "regex-2024.5.15-cp310-cp310-win_amd64.whl", hash = "sha256:ac394ff680fc46b97487941f5e6ae49a9f30ea41c6c6804832063f14b2a5a145"},
+ {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f5b1dff3ad008dccf18e652283f5e5339d70bf8ba7c98bf848ac33db10f7bc7a"},
+ {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c6a2b494a76983df8e3d3feea9b9ffdd558b247e60b92f877f93a1ff43d26656"},
+ {file = "regex-2024.5.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a32b96f15c8ab2e7d27655969a23895eb799de3665fa94349f3b2fbfd547236f"},
+ {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10002e86e6068d9e1c91eae8295ef690f02f913c57db120b58fdd35a6bb1af35"},
+ {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec54d5afa89c19c6dd8541a133be51ee1017a38b412b1321ccb8d6ddbeb4cf7d"},
+ {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10e4ce0dca9ae7a66e6089bb29355d4432caed736acae36fef0fdd7879f0b0cb"},
+ {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e507ff1e74373c4d3038195fdd2af30d297b4f0950eeda6f515ae3d84a1770f"},
+ {file = "regex-2024.5.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1f059a4d795e646e1c37665b9d06062c62d0e8cc3c511fe01315973a6542e40"},
+ {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0721931ad5fe0dda45d07f9820b90b2148ccdd8e45bb9e9b42a146cb4f695649"},
+ {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:833616ddc75ad595dee848ad984d067f2f31be645d603e4d158bba656bbf516c"},
+ {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:287eb7f54fc81546346207c533ad3c2c51a8d61075127d7f6d79aaf96cdee890"},
+ {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:19dfb1c504781a136a80ecd1fff9f16dddf5bb43cec6871778c8a907a085bb3d"},
+ {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:119af6e56dce35e8dfb5222573b50c89e5508d94d55713c75126b753f834de68"},
+ {file = "regex-2024.5.15-cp311-cp311-win32.whl", hash = "sha256:1c1c174d6ec38d6c8a7504087358ce9213d4332f6293a94fbf5249992ba54efa"},
+ {file = "regex-2024.5.15-cp311-cp311-win_amd64.whl", hash = "sha256:9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201"},
+ {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:632b01153e5248c134007209b5c6348a544ce96c46005d8456de1d552455b014"},
+ {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e64198f6b856d48192bf921421fdd8ad8eb35e179086e99e99f711957ffedd6e"},
+ {file = "regex-2024.5.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68811ab14087b2f6e0fc0c2bae9ad689ea3584cad6917fc57be6a48bbd012c49"},
+ {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ec0c2fea1e886a19c3bee0cd19d862b3aa75dcdfb42ebe8ed30708df64687a"},
+ {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d0c0c0003c10f54a591d220997dd27d953cd9ccc1a7294b40a4be5312be8797b"},
+ {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2431b9e263af1953c55abbd3e2efca67ca80a3de8a0437cb58e2421f8184717a"},
+ {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a605586358893b483976cffc1723fb0f83e526e8f14c6e6614e75919d9862cf"},
+ {file = "regex-2024.5.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391d7f7f1e409d192dba8bcd42d3e4cf9e598f3979cdaed6ab11288da88cb9f2"},
+ {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9ff11639a8d98969c863d4617595eb5425fd12f7c5ef6621a4b74b71ed8726d5"},
+ {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4eee78a04e6c67e8391edd4dad3279828dd66ac4b79570ec998e2155d2e59fd5"},
+ {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8fe45aa3f4aa57faabbc9cb46a93363edd6197cbc43523daea044e9ff2fea83e"},
+ {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d0a3d8d6acf0c78a1fff0e210d224b821081330b8524e3e2bc5a68ef6ab5803d"},
+ {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c486b4106066d502495b3025a0a7251bf37ea9540433940a23419461ab9f2a80"},
+ {file = "regex-2024.5.15-cp312-cp312-win32.whl", hash = "sha256:c49e15eac7c149f3670b3e27f1f28a2c1ddeccd3a2812cba953e01be2ab9b5fe"},
+ {file = "regex-2024.5.15-cp312-cp312-win_amd64.whl", hash = "sha256:673b5a6da4557b975c6c90198588181029c60793835ce02f497ea817ff647cb2"},
+ {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:87e2a9c29e672fc65523fb47a90d429b70ef72b901b4e4b1bd42387caf0d6835"},
+ {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c3bea0ba8b73b71b37ac833a7f3fd53825924165da6a924aec78c13032f20850"},
+ {file = "regex-2024.5.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bfc4f82cabe54f1e7f206fd3d30fda143f84a63fe7d64a81558d6e5f2e5aaba9"},
+ {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5bb9425fe881d578aeca0b2b4b3d314ec88738706f66f219c194d67179337cb"},
+ {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64c65783e96e563103d641760664125e91bd85d8e49566ee560ded4da0d3e704"},
+ {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf2430df4148b08fb4324b848672514b1385ae3807651f3567871f130a728cc3"},
+ {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5397de3219a8b08ae9540c48f602996aa6b0b65d5a61683e233af8605c42b0f2"},
+ {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:455705d34b4154a80ead722f4f185b04c4237e8e8e33f265cd0798d0e44825fa"},
+ {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2b6f1b3bb6f640c1a92be3bbfbcb18657b125b99ecf141fb3310b5282c7d4ed"},
+ {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3ad070b823ca5890cab606c940522d05d3d22395d432f4aaaf9d5b1653e47ced"},
+ {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5b5467acbfc153847d5adb21e21e29847bcb5870e65c94c9206d20eb4e99a384"},
+ {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:e6662686aeb633ad65be2a42b4cb00178b3fbf7b91878f9446075c404ada552f"},
+ {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:2b4c884767504c0e2401babe8b5b7aea9148680d2e157fa28f01529d1f7fcf67"},
+ {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3cd7874d57f13bf70078f1ff02b8b0aa48d5b9ed25fc48547516c6aba36f5741"},
+ {file = "regex-2024.5.15-cp38-cp38-win32.whl", hash = "sha256:e4682f5ba31f475d58884045c1a97a860a007d44938c4c0895f41d64481edbc9"},
+ {file = "regex-2024.5.15-cp38-cp38-win_amd64.whl", hash = "sha256:d99ceffa25ac45d150e30bd9ed14ec6039f2aad0ffa6bb87a5936f5782fc1569"},
+ {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13cdaf31bed30a1e1c2453ef6015aa0983e1366fad2667657dbcac7b02f67133"},
+ {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cac27dcaa821ca271855a32188aa61d12decb6fe45ffe3e722401fe61e323cd1"},
+ {file = "regex-2024.5.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7dbe2467273b875ea2de38ded4eba86cbcbc9a1a6d0aa11dcf7bd2e67859c435"},
+ {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64f18a9a3513a99c4bef0e3efd4c4a5b11228b48aa80743be822b71e132ae4f5"},
+ {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d347a741ea871c2e278fde6c48f85136c96b8659b632fb57a7d1ce1872547600"},
+ {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1878b8301ed011704aea4c806a3cadbd76f84dece1ec09cc9e4dc934cfa5d4da"},
+ {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4babf07ad476aaf7830d77000874d7611704a7fcf68c9c2ad151f5d94ae4bfc4"},
+ {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35cb514e137cb3488bce23352af3e12fb0dbedd1ee6e60da053c69fb1b29cc6c"},
+ {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cdd09d47c0b2efee9378679f8510ee6955d329424c659ab3c5e3a6edea696294"},
+ {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:72d7a99cd6b8f958e85fc6ca5b37c4303294954eac1376535b03c2a43eb72629"},
+ {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a094801d379ab20c2135529948cb84d417a2169b9bdceda2a36f5f10977ebc16"},
+ {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c0c18345010870e58238790a6779a1219b4d97bd2e77e1140e8ee5d14df071aa"},
+ {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:16093f563098448ff6b1fa68170e4acbef94e6b6a4e25e10eae8598bb1694b5d"},
+ {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e38a7d4e8f633a33b4c7350fbd8bad3b70bf81439ac67ac38916c4a86b465456"},
+ {file = "regex-2024.5.15-cp39-cp39-win32.whl", hash = "sha256:71a455a3c584a88f654b64feccc1e25876066c4f5ef26cd6dd711308aa538694"},
+ {file = "regex-2024.5.15-cp39-cp39-win_amd64.whl", hash = "sha256:cab12877a9bdafde5500206d1020a584355a97884dfd388af3699e9137bf7388"},
+ {file = "regex-2024.5.15.tar.gz", hash = "sha256:d3ee02d9e5f482cc8309134a91eeaacbdd2261ba111b0fef3748eeb4913e6a2c"},
]
[[package]]
name = "requests"
-version = "2.31.0"
+version = "2.32.3"
description = "Python HTTP for Humans."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"},
- {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},
+ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
+ {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
]
[package.dependencies]
@@ -2723,141 +2816,110 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"]
[[package]]
name = "rlp"
-version = "4.0.0"
+version = "4.0.1"
description = "rlp: A package for Recursive Length Prefix encoding and decoding"
optional = false
-python-versions = ">=3.8, <4"
+python-versions = "<4,>=3.8"
files = [
- {file = "rlp-4.0.0-py3-none-any.whl", hash = "sha256:1747fd933e054e6d25abfe591be92e19a4193a56c93981c05bd0f84dfe279f14"},
- {file = "rlp-4.0.0.tar.gz", hash = "sha256:61a5541f86e4684ab145cb849a5929d2ced8222930a570b3941cf4af16b72a78"},
+ {file = "rlp-4.0.1-py3-none-any.whl", hash = "sha256:ff6846c3c27b97ee0492373aa074a7c3046aadd973320f4fffa7ac45564b0258"},
+ {file = "rlp-4.0.1.tar.gz", hash = "sha256:bcefb11013dfadf8902642337923bd0c786dc8a27cb4c21da6e154e52869ecb1"},
]
[package.dependencies]
eth-utils = ">=2"
[package.extras]
-dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "hypothesis (==5.19.0)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"]
-docs = ["sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"]
-rust-backend = ["rusty-rlp (>=0.2.1,<0.3)"]
+dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "hypothesis (==5.19.0)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"]
+docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"]
+rust-backend = ["rusty-rlp (>=0.2.1)"]
test = ["hypothesis (==5.19.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"]
[[package]]
-name = "rpds-py"
-version = "0.18.0"
-description = "Python bindings to Rust's persistent data structures (rpds)"
+name = "ruamel-yaml"
+version = "0.18.6"
+description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order"
optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.7"
+files = [
+ {file = "ruamel.yaml-0.18.6-py3-none-any.whl", hash = "sha256:57b53ba33def16c4f3d807c0ccbc00f8a6081827e81ba2491691b76882d0c636"},
+ {file = "ruamel.yaml-0.18.6.tar.gz", hash = "sha256:8b27e6a217e786c6fbe5634d8f3f11bc63e0f80f6a5890f28863d9c45aac311b"},
+]
+
+[package.dependencies]
+"ruamel.yaml.clib" = {version = ">=0.2.7", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.13\""}
+
+[package.extras]
+docs = ["mercurial (>5.7)", "ryd"]
+jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"]
+
+[[package]]
+name = "ruamel-yaml-clib"
+version = "0.2.8"
+description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml"
+optional = false
+python-versions = ">=3.6"
files = [
- {file = "rpds_py-0.18.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:5b4e7d8d6c9b2e8ee2d55c90b59c707ca59bc30058269b3db7b1f8df5763557e"},
- {file = "rpds_py-0.18.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c463ed05f9dfb9baebef68048aed8dcdc94411e4bf3d33a39ba97e271624f8f7"},
- {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01e36a39af54a30f28b73096dd39b6802eddd04c90dbe161c1b8dbe22353189f"},
- {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d62dec4976954a23d7f91f2f4530852b0c7608116c257833922a896101336c51"},
- {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd18772815d5f008fa03d2b9a681ae38d5ae9f0e599f7dda233c439fcaa00d40"},
- {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:923d39efa3cfb7279a0327e337a7958bff00cc447fd07a25cddb0a1cc9a6d2da"},
- {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39514da80f971362f9267c600b6d459bfbbc549cffc2cef8e47474fddc9b45b1"},
- {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a34d557a42aa28bd5c48a023c570219ba2593bcbbb8dc1b98d8cf5d529ab1434"},
- {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:93df1de2f7f7239dc9cc5a4a12408ee1598725036bd2dedadc14d94525192fc3"},
- {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:34b18ba135c687f4dac449aa5157d36e2cbb7c03cbea4ddbd88604e076aa836e"},
- {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c0b5dcf9193625afd8ecc92312d6ed78781c46ecbf39af9ad4681fc9f464af88"},
- {file = "rpds_py-0.18.0-cp310-none-win32.whl", hash = "sha256:c4325ff0442a12113a6379af66978c3fe562f846763287ef66bdc1d57925d337"},
- {file = "rpds_py-0.18.0-cp310-none-win_amd64.whl", hash = "sha256:7223a2a5fe0d217e60a60cdae28d6949140dde9c3bcc714063c5b463065e3d66"},
- {file = "rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4"},
- {file = "rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6"},
- {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58"},
- {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d68c93e381010662ab873fea609bf6c0f428b6d0bb00f2c6939782e0818d37bf"},
- {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b34b7aa8b261c1dbf7720b5d6f01f38243e9b9daf7e6b8bc1fd4657000062f2c"},
- {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e6d75ab12b0bbab7215e5d40f1e5b738aa539598db27ef83b2ec46747df90e1"},
- {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5"},
- {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aec493917dd45e3c69d00a8874e7cbed844efd935595ef78a0f25f14312e33c6"},
- {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:661d25cbffaf8cc42e971dd570d87cb29a665f49f4abe1f9e76be9a5182c4688"},
- {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1df3659d26f539ac74fb3b0c481cdf9d725386e3552c6fa2974f4d33d78e544b"},
- {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1ce3ba137ed54f83e56fb983a5859a27d43a40188ba798993812fed73c70836"},
- {file = "rpds_py-0.18.0-cp311-none-win32.whl", hash = "sha256:69e64831e22a6b377772e7fb337533c365085b31619005802a79242fee620bc1"},
- {file = "rpds_py-0.18.0-cp311-none-win_amd64.whl", hash = "sha256:998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa"},
- {file = "rpds_py-0.18.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7f2facbd386dd60cbbf1a794181e6aa0bd429bd78bfdf775436020172e2a23f0"},
- {file = "rpds_py-0.18.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1d9a5be316c15ffb2b3c405c4ff14448c36b4435be062a7f578ccd8b01f0c4d8"},
- {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd5bf1af8efe569654bbef5a3e0a56eca45f87cfcffab31dd8dde70da5982475"},
- {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5417558f6887e9b6b65b4527232553c139b57ec42c64570569b155262ac0754f"},
- {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:56a737287efecafc16f6d067c2ea0117abadcd078d58721f967952db329a3e5c"},
- {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8f03bccbd8586e9dd37219bce4d4e0d3ab492e6b3b533e973fa08a112cb2ffc9"},
- {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4457a94da0d5c53dc4b3e4de1158bdab077db23c53232f37a3cb7afdb053a4e3"},
- {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0ab39c1ba9023914297dd88ec3b3b3c3f33671baeb6acf82ad7ce883f6e8e157"},
- {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9d54553c1136b50fd12cc17e5b11ad07374c316df307e4cfd6441bea5fb68496"},
- {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0af039631b6de0397ab2ba16eaf2872e9f8fca391b44d3d8cac317860a700a3f"},
- {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:84ffab12db93b5f6bad84c712c92060a2d321b35c3c9960b43d08d0f639d60d7"},
- {file = "rpds_py-0.18.0-cp312-none-win32.whl", hash = "sha256:685537e07897f173abcf67258bee3c05c374fa6fff89d4c7e42fb391b0605e98"},
- {file = "rpds_py-0.18.0-cp312-none-win_amd64.whl", hash = "sha256:e003b002ec72c8d5a3e3da2989c7d6065b47d9eaa70cd8808b5384fbb970f4ec"},
- {file = "rpds_py-0.18.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:08f9ad53c3f31dfb4baa00da22f1e862900f45908383c062c27628754af2e88e"},
- {file = "rpds_py-0.18.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0013fe6b46aa496a6749c77e00a3eb07952832ad6166bd481c74bda0dcb6d58"},
- {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32a92116d4f2a80b629778280103d2a510a5b3f6314ceccd6e38006b5e92dcb"},
- {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e541ec6f2ec456934fd279a3120f856cd0aedd209fc3852eca563f81738f6861"},
- {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bed88b9a458e354014d662d47e7a5baafd7ff81c780fd91584a10d6ec842cb73"},
- {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2644e47de560eb7bd55c20fc59f6daa04682655c58d08185a9b95c1970fa1e07"},
- {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e8916ae4c720529e18afa0b879473049e95949bf97042e938530e072fde061d"},
- {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:465a3eb5659338cf2a9243e50ad9b2296fa15061736d6e26240e713522b6235c"},
- {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ea7d4a99f3b38c37eac212dbd6ec42b7a5ec51e2c74b5d3223e43c811609e65f"},
- {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:67071a6171e92b6da534b8ae326505f7c18022c6f19072a81dcf40db2638767c"},
- {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:41ef53e7c58aa4ef281da975f62c258950f54b76ec8e45941e93a3d1d8580594"},
- {file = "rpds_py-0.18.0-cp38-none-win32.whl", hash = "sha256:fdea4952db2793c4ad0bdccd27c1d8fdd1423a92f04598bc39425bcc2b8ee46e"},
- {file = "rpds_py-0.18.0-cp38-none-win_amd64.whl", hash = "sha256:7cd863afe7336c62ec78d7d1349a2f34c007a3cc6c2369d667c65aeec412a5b1"},
- {file = "rpds_py-0.18.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5307def11a35f5ae4581a0b658b0af8178c65c530e94893345bebf41cc139d33"},
- {file = "rpds_py-0.18.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77f195baa60a54ef9d2de16fbbfd3ff8b04edc0c0140a761b56c267ac11aa467"},
- {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39f5441553f1c2aed4de4377178ad8ff8f9d733723d6c66d983d75341de265ab"},
- {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a00312dea9310d4cb7dbd7787e722d2e86a95c2db92fbd7d0155f97127bcb40"},
- {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f2fc11e8fe034ee3c34d316d0ad8808f45bc3b9ce5857ff29d513f3ff2923a1"},
- {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:586f8204935b9ec884500498ccc91aa869fc652c40c093bd9e1471fbcc25c022"},
- {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddc2f4dfd396c7bfa18e6ce371cba60e4cf9d2e5cdb71376aa2da264605b60b9"},
- {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ddcba87675b6d509139d1b521e0c8250e967e63b5909a7e8f8944d0f90ff36f"},
- {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7bd339195d84439cbe5771546fe8a4e8a7a045417d8f9de9a368c434e42a721e"},
- {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:d7c36232a90d4755b720fbd76739d8891732b18cf240a9c645d75f00639a9024"},
- {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6b0817e34942b2ca527b0e9298373e7cc75f429e8da2055607f4931fded23e20"},
- {file = "rpds_py-0.18.0-cp39-none-win32.whl", hash = "sha256:99f70b740dc04d09e6b2699b675874367885217a2e9f782bdf5395632ac663b7"},
- {file = "rpds_py-0.18.0-cp39-none-win_amd64.whl", hash = "sha256:6ef687afab047554a2d366e112dd187b62d261d49eb79b77e386f94644363294"},
- {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ad36cfb355e24f1bd37cac88c112cd7730873f20fb0bdaf8ba59eedf8216079f"},
- {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:36b3ee798c58ace201289024b52788161e1ea133e4ac93fba7d49da5fec0ef9e"},
- {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8a2f084546cc59ea99fda8e070be2fd140c3092dc11524a71aa8f0f3d5a55ca"},
- {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e4461d0f003a0aa9be2bdd1b798a041f177189c1a0f7619fe8c95ad08d9a45d7"},
- {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8db715ebe3bb7d86d77ac1826f7d67ec11a70dbd2376b7cc214199360517b641"},
- {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793968759cd0d96cac1e367afd70c235867831983f876a53389ad869b043c948"},
- {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66e6a3af5a75363d2c9a48b07cb27c4ea542938b1a2e93b15a503cdfa8490795"},
- {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ef0befbb5d79cf32d0266f5cff01545602344eda89480e1dd88aca964260b18"},
- {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1d4acf42190d449d5e89654d5c1ed3a4f17925eec71f05e2a41414689cda02d1"},
- {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:a5f446dd5055667aabaee78487f2b5ab72e244f9bc0b2ffebfeec79051679984"},
- {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9dbbeb27f4e70bfd9eec1be5477517365afe05a9b2c441a0b21929ee61048124"},
- {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:22806714311a69fd0af9b35b7be97c18a0fc2826e6827dbb3a8c94eac6cf7eeb"},
- {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b34ae4636dfc4e76a438ab826a0d1eed2589ca7d9a1b2d5bb546978ac6485461"},
- {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c8370641f1a7f0e0669ddccca22f1da893cef7628396431eb445d46d893e5cd"},
- {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c8362467a0fdeccd47935f22c256bec5e6abe543bf0d66e3d3d57a8fb5731863"},
- {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11a8c85ef4a07a7638180bf04fe189d12757c696eb41f310d2426895356dcf05"},
- {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b316144e85316da2723f9d8dc75bada12fa58489a527091fa1d5a612643d1a0e"},
- {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf1ea2e34868f6fbf070e1af291c8180480310173de0b0c43fc38a02929fc0e3"},
- {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e546e768d08ad55b20b11dbb78a745151acbd938f8f00d0cfbabe8b0199b9880"},
- {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4901165d170a5fde6f589acb90a6b33629ad1ec976d4529e769c6f3d885e3e80"},
- {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:618a3d6cae6ef8ec88bb76dd80b83cfe415ad4f1d942ca2a903bf6b6ff97a2da"},
- {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ed4eb745efbff0a8e9587d22a84be94a5eb7d2d99c02dacf7bd0911713ed14dd"},
- {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6c81e5f372cd0dc5dc4809553d34f832f60a46034a5f187756d9b90586c2c307"},
- {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:43fbac5f22e25bee1d482c97474f930a353542855f05c1161fd804c9dc74a09d"},
- {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d7faa6f14017c0b1e69f5e2c357b998731ea75a442ab3841c0dbbbfe902d2c4"},
- {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:08231ac30a842bd04daabc4d71fddd7e6d26189406d5a69535638e4dcb88fe76"},
- {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:044a3e61a7c2dafacae99d1e722cc2d4c05280790ec5a05031b3876809d89a5c"},
- {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3f26b5bd1079acdb0c7a5645e350fe54d16b17bfc5e71f371c449383d3342e17"},
- {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:482103aed1dfe2f3b71a58eff35ba105289b8d862551ea576bd15479aba01f66"},
- {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1374f4129f9bcca53a1bba0bb86bf78325a0374577cf7e9e4cd046b1e6f20e24"},
- {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:635dc434ff724b178cb192c70016cc0ad25a275228f749ee0daf0eddbc8183b1"},
- {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:bc362ee4e314870a70f4ae88772d72d877246537d9f8cb8f7eacf10884862432"},
- {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:4832d7d380477521a8c1644bbab6588dfedea5e30a7d967b5fb75977c45fd77f"},
- {file = "rpds_py-0.18.0.tar.gz", hash = "sha256:42821446ee7a76f5d9f71f9e33a4fb2ffd724bb3e7f93386150b61a43115788d"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b42169467c42b692c19cf539c38d4602069d8c1505e97b86387fcf7afb766e1d"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:07238db9cbdf8fc1e9de2489a4f68474e70dffcb32232db7c08fa61ca0c7c462"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fff3573c2db359f091e1589c3d7c5fc2f86f5bdb6f24252c2d8e539d4e45f412"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:aa2267c6a303eb483de8d02db2871afb5c5fc15618d894300b88958f729ad74f"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:840f0c7f194986a63d2c2465ca63af8ccbbc90ab1c6001b1978f05119b5e7334"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:024cfe1fc7c7f4e1aff4a81e718109e13409767e4f871443cbff3dba3578203d"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win32.whl", hash = "sha256:c69212f63169ec1cfc9bb44723bf2917cbbd8f6191a00ef3410f5a7fe300722d"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win_amd64.whl", hash = "sha256:cabddb8d8ead485e255fe80429f833172b4cadf99274db39abc080e068cbcc31"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bef08cd86169d9eafb3ccb0a39edb11d8e25f3dae2b28f5c52fd997521133069"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:b16420e621d26fdfa949a8b4b47ade8810c56002f5389970db4ddda51dbff248"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:25c515e350e5b739842fc3228d662413ef28f295791af5e5110b543cf0b57d9b"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_24_aarch64.whl", hash = "sha256:1707814f0d9791df063f8c19bb51b0d1278b8e9a2353abbb676c2f685dee6afe"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:46d378daaac94f454b3a0e3d8d78cafd78a026b1d71443f4966c696b48a6d899"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:09b055c05697b38ecacb7ac50bdab2240bfca1a0c4872b0fd309bb07dc9aa3a9"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win32.whl", hash = "sha256:53a300ed9cea38cf5a2a9b069058137c2ca1ce658a874b79baceb8f892f915a7"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win_amd64.whl", hash = "sha256:c2a72e9109ea74e511e29032f3b670835f8a59bbdc9ce692c5b4ed91ccf1eedb"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ebc06178e8821efc9692ea7544aa5644217358490145629914d8020042c24aa1"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:edaef1c1200c4b4cb914583150dcaa3bc30e592e907c01117c08b13a07255ec2"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d176b57452ab5b7028ac47e7b3cf644bcfdc8cacfecf7e71759f7f51a59e5c92"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_24_aarch64.whl", hash = "sha256:1dc67314e7e1086c9fdf2680b7b6c2be1c0d8e3a8279f2e993ca2a7545fecf62"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3213ece08ea033eb159ac52ae052a4899b56ecc124bb80020d9bbceeb50258e9"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aab7fd643f71d7946f2ee58cc88c9b7bfc97debd71dcc93e03e2d174628e7e2d"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win32.whl", hash = "sha256:5c365d91c88390c8d0a8545df0b5857172824b1c604e867161e6b3d59a827eaa"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win_amd64.whl", hash = "sha256:1758ce7d8e1a29d23de54a16ae867abd370f01b5a69e1a3ba75223eaa3ca1a1b"},
+ {file = "ruamel.yaml.clib-0.2.8-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a5aa27bad2bb83670b71683aae140a1f52b0857a2deff56ad3f6c13a017a26ed"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c58ecd827313af6864893e7af0a3bb85fd529f862b6adbefe14643947cfe2942"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f481f16baec5290e45aebdc2a5168ebc6d35189ae6fea7a58787613a25f6e875"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:77159f5d5b5c14f7c34073862a6b7d34944075d9f93e681638f6d753606c6ce6"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7f67a1ee819dc4562d444bbafb135832b0b909f81cc90f7aa00260968c9ca1b3"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4ecbf9c3e19f9562c7fdd462e8d18dd902a47ca046a2e64dba80699f0b6c09b7"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:87ea5ff66d8064301a154b3933ae406b0863402a799b16e4a1d24d9fbbcbe0d3"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win32.whl", hash = "sha256:75e1ed13e1f9de23c5607fe6bd1aeaae21e523b32d83bb33918245361e9cc51b"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win_amd64.whl", hash = "sha256:3f215c5daf6a9d7bbed4a0a4f760f3113b10e82ff4c5c44bec20a68c8014f675"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1b617618914cb00bf5c34d4357c37aa15183fa229b24767259657746c9077615"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:a6a9ffd280b71ad062eae53ac1659ad86a17f59a0fdc7699fd9be40525153337"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:305889baa4043a09e5b76f8e2a51d4ffba44259f6b4c72dec8ca56207d9c6fe1"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:700e4ebb569e59e16a976857c8798aee258dceac7c7d6b50cab63e080058df91"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e2b4c44b60eadec492926a7270abb100ef9f72798e18743939bdbf037aab8c28"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e79e5db08739731b0ce4850bed599235d601701d5694c36570a99a0c5ca41a9d"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win32.whl", hash = "sha256:955eae71ac26c1ab35924203fda6220f84dce57d6d7884f189743e2abe3a9fbe"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win_amd64.whl", hash = "sha256:56f4252222c067b4ce51ae12cbac231bce32aee1d33fbfc9d17e5b8d6966c312"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03d1162b6d1df1caa3a4bd27aa51ce17c9afc2046c31b0ad60a0a96ec22f8001"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba64af9fa9cebe325a62fa398760f5c7206b215201b0ec825005f1b18b9bccf"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:a1a45e0bb052edf6a1d3a93baef85319733a888363938e1fc9924cb00c8df24c"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:da09ad1c359a728e112d60116f626cc9f29730ff3e0e7db72b9a2dbc2e4beed5"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:184565012b60405d93838167f425713180b949e9d8dd0bbc7b49f074407c5a8b"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a75879bacf2c987c003368cf14bed0ffe99e8e85acfa6c0bfffc21a090f16880"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win32.whl", hash = "sha256:84b554931e932c46f94ab306913ad7e11bba988104c5cff26d90d03f68258cd5"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win_amd64.whl", hash = "sha256:25ac8c08322002b06fa1d49d1646181f0b2c72f5cbc15a85e80b4c30a544bb15"},
+ {file = "ruamel.yaml.clib-0.2.8.tar.gz", hash = "sha256:beb2e0404003de9a4cab9753a8805a8fe9320ee6673136ed7f04255fe60bb512"},
]
[[package]]
name = "s3transfer"
-version = "0.10.0"
+version = "0.10.1"
description = "An Amazon S3 Transfer Manager"
optional = false
python-versions = ">= 3.8"
files = [
- {file = "s3transfer-0.10.0-py3-none-any.whl", hash = "sha256:3cdb40f5cfa6966e812209d0994f2a4709b561c88e90cf00c2696d2df4e56b2e"},
- {file = "s3transfer-0.10.0.tar.gz", hash = "sha256:d0c8bbf672d5eebbe4e57945e23b972d963f07d82f661cabf678a5c88831595b"},
+ {file = "s3transfer-0.10.1-py3-none-any.whl", hash = "sha256:ceb252b11bcf87080fb7850a224fb6e05c8a776bab8f2b64b7f25b969464839d"},
+ {file = "s3transfer-0.10.1.tar.gz", hash = "sha256:5683916b4c724f799e600f41dd9e10a9ff19871bf87623cc8f491cb4f5fa0a19"},
]
[package.dependencies]
@@ -2866,22 +2928,6 @@ botocore = ">=1.33.2,<2.0a.0"
[package.extras]
crt = ["botocore[crt] (>=1.33.2,<2.0a.0)"]
-[[package]]
-name = "setuptools"
-version = "69.1.1"
-description = "Easily download, build, install, upgrade, and uninstall Python packages"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "setuptools-69.1.1-py3-none-any.whl", hash = "sha256:02fa291a0471b3a18b2b2481ed902af520c69e8ae0919c13da936542754b4c56"},
- {file = "setuptools-69.1.1.tar.gz", hash = "sha256:5c0806c7d9af348e6dd3777b4f4dbb42c7ad85b190104837488eab9a7c945cf8"},
-]
-
-[package.extras]
-docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
-testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
-testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
-
[[package]]
name = "shared-memory-dict"
version = "0.7.2"
@@ -2898,6 +2944,17 @@ aiocache = ["aiocache (>=0.11.1,<0.12.0)"]
all = ["aiocache (>=0.11.1,<0.12.0)", "django (>=3.0.8,<4.0.0)"]
django = ["django (>=3.0.8,<4.0.0)"]
+[[package]]
+name = "shellingham"
+version = "1.5.4"
+description = "Tool to Detect Surrounding Shell"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"},
+ {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"},
+]
+
[[package]]
name = "six"
version = "1.16.0"
@@ -2922,60 +2979,60 @@ files = [
[[package]]
name = "sqlalchemy"
-version = "2.0.28"
+version = "2.0.30"
description = "Database Abstraction Library"
optional = false
python-versions = ">=3.7"
files = [
- {file = "SQLAlchemy-2.0.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0b148ab0438f72ad21cb004ce3bdaafd28465c4276af66df3b9ecd2037bf252"},
- {file = "SQLAlchemy-2.0.28-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bbda76961eb8f27e6ad3c84d1dc56d5bc61ba8f02bd20fcf3450bd421c2fcc9c"},
- {file = "SQLAlchemy-2.0.28-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feea693c452d85ea0015ebe3bb9cd15b6f49acc1a31c28b3c50f4db0f8fb1e71"},
- {file = "SQLAlchemy-2.0.28-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5da98815f82dce0cb31fd1e873a0cb30934971d15b74e0d78cf21f9e1b05953f"},
- {file = "SQLAlchemy-2.0.28-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a5adf383c73f2d49ad15ff363a8748319ff84c371eed59ffd0127355d6ea1da"},
- {file = "SQLAlchemy-2.0.28-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56856b871146bfead25fbcaed098269d90b744eea5cb32a952df00d542cdd368"},
- {file = "SQLAlchemy-2.0.28-cp310-cp310-win32.whl", hash = "sha256:943aa74a11f5806ab68278284a4ddd282d3fb348a0e96db9b42cb81bf731acdc"},
- {file = "SQLAlchemy-2.0.28-cp310-cp310-win_amd64.whl", hash = "sha256:c6c4da4843e0dabde41b8f2e8147438330924114f541949e6318358a56d1875a"},
- {file = "SQLAlchemy-2.0.28-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46a3d4e7a472bfff2d28db838669fc437964e8af8df8ee1e4548e92710929adc"},
- {file = "SQLAlchemy-2.0.28-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0d3dd67b5d69794cfe82862c002512683b3db038b99002171f624712fa71aeaa"},
- {file = "SQLAlchemy-2.0.28-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61e2e41656a673b777e2f0cbbe545323dbe0d32312f590b1bc09da1de6c2a02"},
- {file = "SQLAlchemy-2.0.28-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0315d9125a38026227f559488fe7f7cee1bd2fbc19f9fd637739dc50bb6380b2"},
- {file = "SQLAlchemy-2.0.28-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:af8ce2d31679006e7b747d30a89cd3ac1ec304c3d4c20973f0f4ad58e2d1c4c9"},
- {file = "SQLAlchemy-2.0.28-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:81ba314a08c7ab701e621b7ad079c0c933c58cdef88593c59b90b996e8b58fa5"},
- {file = "SQLAlchemy-2.0.28-cp311-cp311-win32.whl", hash = "sha256:1ee8bd6d68578e517943f5ebff3afbd93fc65f7ef8f23becab9fa8fb315afb1d"},
- {file = "SQLAlchemy-2.0.28-cp311-cp311-win_amd64.whl", hash = "sha256:ad7acbe95bac70e4e687a4dc9ae3f7a2f467aa6597049eeb6d4a662ecd990bb6"},
- {file = "SQLAlchemy-2.0.28-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d3499008ddec83127ab286c6f6ec82a34f39c9817f020f75eca96155f9765097"},
- {file = "SQLAlchemy-2.0.28-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9b66fcd38659cab5d29e8de5409cdf91e9986817703e1078b2fdaad731ea66f5"},
- {file = "SQLAlchemy-2.0.28-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bea30da1e76cb1acc5b72e204a920a3a7678d9d52f688f087dc08e54e2754c67"},
- {file = "SQLAlchemy-2.0.28-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:124202b4e0edea7f08a4db8c81cc7859012f90a0d14ba2bf07c099aff6e96462"},
- {file = "SQLAlchemy-2.0.28-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e23b88c69497a6322b5796c0781400692eca1ae5532821b39ce81a48c395aae9"},
- {file = "SQLAlchemy-2.0.28-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b6303bfd78fb3221847723104d152e5972c22367ff66edf09120fcde5ddc2e2"},
- {file = "SQLAlchemy-2.0.28-cp312-cp312-win32.whl", hash = "sha256:a921002be69ac3ab2cf0c3017c4e6a3377f800f1fca7f254c13b5f1a2f10022c"},
- {file = "SQLAlchemy-2.0.28-cp312-cp312-win_amd64.whl", hash = "sha256:b4a2cf92995635b64876dc141af0ef089c6eea7e05898d8d8865e71a326c0385"},
- {file = "SQLAlchemy-2.0.28-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e91b5e341f8c7f1e5020db8e5602f3ed045a29f8e27f7f565e0bdee3338f2c7"},
- {file = "SQLAlchemy-2.0.28-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45c7b78dfc7278329f27be02c44abc0d69fe235495bb8e16ec7ef1b1a17952db"},
- {file = "SQLAlchemy-2.0.28-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3eba73ef2c30695cb7eabcdb33bb3d0b878595737479e152468f3ba97a9c22a4"},
- {file = "SQLAlchemy-2.0.28-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5df5d1dafb8eee89384fb7a1f79128118bc0ba50ce0db27a40750f6f91aa99d5"},
- {file = "SQLAlchemy-2.0.28-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2858bbab1681ee5406650202950dc8f00e83b06a198741b7c656e63818633526"},
- {file = "SQLAlchemy-2.0.28-cp37-cp37m-win32.whl", hash = "sha256:9461802f2e965de5cff80c5a13bc945abea7edaa1d29360b485c3d2b56cdb075"},
- {file = "SQLAlchemy-2.0.28-cp37-cp37m-win_amd64.whl", hash = "sha256:a6bec1c010a6d65b3ed88c863d56b9ea5eeefdf62b5e39cafd08c65f5ce5198b"},
- {file = "SQLAlchemy-2.0.28-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:843a882cadebecc655a68bd9a5b8aa39b3c52f4a9a5572a3036fb1bb2ccdc197"},
- {file = "SQLAlchemy-2.0.28-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:dbb990612c36163c6072723523d2be7c3eb1517bbdd63fe50449f56afafd1133"},
- {file = "SQLAlchemy-2.0.28-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7e4baf9161d076b9a7e432fce06217b9bd90cfb8f1d543d6e8c4595627edb9"},
- {file = "SQLAlchemy-2.0.28-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0a5354cb4de9b64bccb6ea33162cb83e03dbefa0d892db88a672f5aad638a75"},
- {file = "SQLAlchemy-2.0.28-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:fffcc8edc508801ed2e6a4e7b0d150a62196fd28b4e16ab9f65192e8186102b6"},
- {file = "SQLAlchemy-2.0.28-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aca7b6d99a4541b2ebab4494f6c8c2f947e0df4ac859ced575238e1d6ca5716b"},
- {file = "SQLAlchemy-2.0.28-cp38-cp38-win32.whl", hash = "sha256:8c7f10720fc34d14abad5b647bc8202202f4948498927d9f1b4df0fb1cf391b7"},
- {file = "SQLAlchemy-2.0.28-cp38-cp38-win_amd64.whl", hash = "sha256:243feb6882b06a2af68ecf4bec8813d99452a1b62ba2be917ce6283852cf701b"},
- {file = "SQLAlchemy-2.0.28-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fc4974d3684f28b61b9a90fcb4c41fb340fd4b6a50c04365704a4da5a9603b05"},
- {file = "SQLAlchemy-2.0.28-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:87724e7ed2a936fdda2c05dbd99d395c91ea3c96f029a033a4a20e008dd876bf"},
- {file = "SQLAlchemy-2.0.28-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68722e6a550f5de2e3cfe9da6afb9a7dd15ef7032afa5651b0f0c6b3adb8815d"},
- {file = "SQLAlchemy-2.0.28-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:328529f7c7f90adcd65aed06a161851f83f475c2f664a898af574893f55d9e53"},
- {file = "SQLAlchemy-2.0.28-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:df40c16a7e8be7413b885c9bf900d402918cc848be08a59b022478804ea076b8"},
- {file = "SQLAlchemy-2.0.28-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:426f2fa71331a64f5132369ede5171c52fd1df1bd9727ce621f38b5b24f48750"},
- {file = "SQLAlchemy-2.0.28-cp39-cp39-win32.whl", hash = "sha256:33157920b233bc542ce497a81a2e1452e685a11834c5763933b440fedd1d8e2d"},
- {file = "SQLAlchemy-2.0.28-cp39-cp39-win_amd64.whl", hash = "sha256:2f60843068e432311c886c5f03c4664acaef507cf716f6c60d5fde7265be9d7b"},
- {file = "SQLAlchemy-2.0.28-py3-none-any.whl", hash = "sha256:78bb7e8da0183a8301352d569900d9d3594c48ac21dc1c2ec6b3121ed8b6c986"},
- {file = "SQLAlchemy-2.0.28.tar.gz", hash = "sha256:dd53b6c4e6d960600fd6532b79ee28e2da489322fcf6648738134587faf767b6"},
+ {file = "SQLAlchemy-2.0.30-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3b48154678e76445c7ded1896715ce05319f74b1e73cf82d4f8b59b46e9c0ddc"},
+ {file = "SQLAlchemy-2.0.30-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2753743c2afd061bb95a61a51bbb6a1a11ac1c44292fad898f10c9839a7f75b2"},
+ {file = "SQLAlchemy-2.0.30-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7bfc726d167f425d4c16269a9a10fe8630ff6d14b683d588044dcef2d0f6be7"},
+ {file = "SQLAlchemy-2.0.30-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4f61ada6979223013d9ab83a3ed003ded6959eae37d0d685db2c147e9143797"},
+ {file = "SQLAlchemy-2.0.30-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a365eda439b7a00732638f11072907c1bc8e351c7665e7e5da91b169af794af"},
+ {file = "SQLAlchemy-2.0.30-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bba002a9447b291548e8d66fd8c96a6a7ed4f2def0bb155f4f0a1309fd2735d5"},
+ {file = "SQLAlchemy-2.0.30-cp310-cp310-win32.whl", hash = "sha256:0138c5c16be3600923fa2169532205d18891b28afa817cb49b50e08f62198bb8"},
+ {file = "SQLAlchemy-2.0.30-cp310-cp310-win_amd64.whl", hash = "sha256:99650e9f4cf3ad0d409fed3eec4f071fadd032e9a5edc7270cd646a26446feeb"},
+ {file = "SQLAlchemy-2.0.30-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:955991a09f0992c68a499791a753523f50f71a6885531568404fa0f231832aa0"},
+ {file = "SQLAlchemy-2.0.30-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f69e4c756ee2686767eb80f94c0125c8b0a0b87ede03eacc5c8ae3b54b99dc46"},
+ {file = "SQLAlchemy-2.0.30-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69c9db1ce00e59e8dd09d7bae852a9add716efdc070a3e2068377e6ff0d6fdaa"},
+ {file = "SQLAlchemy-2.0.30-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1429a4b0f709f19ff3b0cf13675b2b9bfa8a7e79990003207a011c0db880a13"},
+ {file = "SQLAlchemy-2.0.30-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:efedba7e13aa9a6c8407c48facfdfa108a5a4128e35f4c68f20c3407e4376aa9"},
+ {file = "SQLAlchemy-2.0.30-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:16863e2b132b761891d6c49f0a0f70030e0bcac4fd208117f6b7e053e68668d0"},
+ {file = "SQLAlchemy-2.0.30-cp311-cp311-win32.whl", hash = "sha256:2ecabd9ccaa6e914e3dbb2aa46b76dede7eadc8cbf1b8083c94d936bcd5ffb49"},
+ {file = "SQLAlchemy-2.0.30-cp311-cp311-win_amd64.whl", hash = "sha256:0b3f4c438e37d22b83e640f825ef0f37b95db9aa2d68203f2c9549375d0b2260"},
+ {file = "SQLAlchemy-2.0.30-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5a79d65395ac5e6b0c2890935bad892eabb911c4aa8e8015067ddb37eea3d56c"},
+ {file = "SQLAlchemy-2.0.30-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9a5baf9267b752390252889f0c802ea13b52dfee5e369527da229189b8bd592e"},
+ {file = "SQLAlchemy-2.0.30-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cb5a646930c5123f8461f6468901573f334c2c63c795b9af350063a736d0134"},
+ {file = "SQLAlchemy-2.0.30-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:296230899df0b77dec4eb799bcea6fbe39a43707ce7bb166519c97b583cfcab3"},
+ {file = "SQLAlchemy-2.0.30-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c62d401223f468eb4da32627bffc0c78ed516b03bb8a34a58be54d618b74d472"},
+ {file = "SQLAlchemy-2.0.30-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3b69e934f0f2b677ec111b4d83f92dc1a3210a779f69bf905273192cf4ed433e"},
+ {file = "SQLAlchemy-2.0.30-cp312-cp312-win32.whl", hash = "sha256:77d2edb1f54aff37e3318f611637171e8ec71472f1fdc7348b41dcb226f93d90"},
+ {file = "SQLAlchemy-2.0.30-cp312-cp312-win_amd64.whl", hash = "sha256:b6c7ec2b1f4969fc19b65b7059ed00497e25f54069407a8701091beb69e591a5"},
+ {file = "SQLAlchemy-2.0.30-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5a8e3b0a7e09e94be7510d1661339d6b52daf202ed2f5b1f9f48ea34ee6f2d57"},
+ {file = "SQLAlchemy-2.0.30-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b60203c63e8f984df92035610c5fb76d941254cf5d19751faab7d33b21e5ddc0"},
+ {file = "SQLAlchemy-2.0.30-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1dc3eabd8c0232ee8387fbe03e0a62220a6f089e278b1f0aaf5e2d6210741ad"},
+ {file = "SQLAlchemy-2.0.30-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:40ad017c672c00b9b663fcfcd5f0864a0a97828e2ee7ab0c140dc84058d194cf"},
+ {file = "SQLAlchemy-2.0.30-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e42203d8d20dc704604862977b1470a122e4892791fe3ed165f041e4bf447a1b"},
+ {file = "SQLAlchemy-2.0.30-cp37-cp37m-win32.whl", hash = "sha256:2a4f4da89c74435f2bc61878cd08f3646b699e7d2eba97144030d1be44e27584"},
+ {file = "SQLAlchemy-2.0.30-cp37-cp37m-win_amd64.whl", hash = "sha256:b6bf767d14b77f6a18b6982cbbf29d71bede087edae495d11ab358280f304d8e"},
+ {file = "SQLAlchemy-2.0.30-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc0c53579650a891f9b83fa3cecd4e00218e071d0ba00c4890f5be0c34887ed3"},
+ {file = "SQLAlchemy-2.0.30-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:311710f9a2ee235f1403537b10c7687214bb1f2b9ebb52702c5aa4a77f0b3af7"},
+ {file = "SQLAlchemy-2.0.30-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:408f8b0e2c04677e9c93f40eef3ab22f550fecb3011b187f66a096395ff3d9fd"},
+ {file = "SQLAlchemy-2.0.30-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37a4b4fb0dd4d2669070fb05b8b8824afd0af57587393015baee1cf9890242d9"},
+ {file = "SQLAlchemy-2.0.30-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a943d297126c9230719c27fcbbeab57ecd5d15b0bd6bfd26e91bfcfe64220621"},
+ {file = "SQLAlchemy-2.0.30-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0a089e218654e740a41388893e090d2e2c22c29028c9d1353feb38638820bbeb"},
+ {file = "SQLAlchemy-2.0.30-cp38-cp38-win32.whl", hash = "sha256:fa561138a64f949f3e889eb9ab8c58e1504ab351d6cf55259dc4c248eaa19da6"},
+ {file = "SQLAlchemy-2.0.30-cp38-cp38-win_amd64.whl", hash = "sha256:7d74336c65705b986d12a7e337ba27ab2b9d819993851b140efdf029248e818e"},
+ {file = "SQLAlchemy-2.0.30-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ae8c62fe2480dd61c532ccafdbce9b29dacc126fe8be0d9a927ca3e699b9491a"},
+ {file = "SQLAlchemy-2.0.30-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2383146973a15435e4717f94c7509982770e3e54974c71f76500a0136f22810b"},
+ {file = "SQLAlchemy-2.0.30-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8409de825f2c3b62ab15788635ccaec0c881c3f12a8af2b12ae4910a0a9aeef6"},
+ {file = "SQLAlchemy-2.0.30-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0094c5dc698a5f78d3d1539853e8ecec02516b62b8223c970c86d44e7a80f6c7"},
+ {file = "SQLAlchemy-2.0.30-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:edc16a50f5e1b7a06a2dcc1f2205b0b961074c123ed17ebda726f376a5ab0953"},
+ {file = "SQLAlchemy-2.0.30-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f7703c2010355dd28f53deb644a05fc30f796bd8598b43f0ba678878780b6e4c"},
+ {file = "SQLAlchemy-2.0.30-cp39-cp39-win32.whl", hash = "sha256:1f9a727312ff6ad5248a4367358e2cf7e625e98b1028b1d7ab7b806b7d757513"},
+ {file = "SQLAlchemy-2.0.30-cp39-cp39-win_amd64.whl", hash = "sha256:a0ef36b28534f2a5771191be6edb44cc2673c7b2edf6deac6562400288664221"},
+ {file = "SQLAlchemy-2.0.30-py3-none-any.whl", hash = "sha256:7108d569d3990c71e26a42f60474b4c02c8586c4681af5fd67e51a044fdea86a"},
+ {file = "SQLAlchemy-2.0.30.tar.gz", hash = "sha256:2b1708916730f4830bc69d6f49d37f7698b5bd7530aca7f04f785f8849e95255"},
]
[package.dependencies]
@@ -3009,13 +3066,13 @@ sqlcipher = ["sqlcipher3_binary"]
[[package]]
name = "starlette"
-version = "0.36.3"
+version = "0.37.2"
description = "The little ASGI library that shines."
optional = false
python-versions = ">=3.8"
files = [
- {file = "starlette-0.36.3-py3-none-any.whl", hash = "sha256:13d429aa93a61dc40bf503e8c801db1f1bca3dc706b10ef2434a36123568f044"},
- {file = "starlette-0.36.3.tar.gz", hash = "sha256:90a671733cfb35771d8cc605e0b679d23b992f8dcfad48cc60b38cb29aeb7080"},
+ {file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"},
+ {file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"},
]
[package.dependencies]
@@ -3075,33 +3132,30 @@ files = [
[[package]]
name = "typer"
-version = "0.7.0"
+version = "0.12.3"
description = "Typer, build great CLIs. Easy to code. Based on Python type hints."
-optional = true
-python-versions = ">=3.6"
+optional = false
+python-versions = ">=3.7"
files = [
- {file = "typer-0.7.0-py3-none-any.whl", hash = "sha256:b5e704f4e48ec263de1c0b3a2387cd405a13767d2f907f44c1a08cbad96f606d"},
- {file = "typer-0.7.0.tar.gz", hash = "sha256:ff797846578a9f2a201b53442aedeb543319466870fbe1c701eab66dd7681165"},
+ {file = "typer-0.12.3-py3-none-any.whl", hash = "sha256:070d7ca53f785acbccba8e7d28b08dcd88f79f1fbda035ade0aecec71ca5c914"},
+ {file = "typer-0.12.3.tar.gz", hash = "sha256:49e73131481d804288ef62598d97a1ceef3058905aa536a1134f90891ba35482"},
]
[package.dependencies]
-click = ">=7.1.1,<9.0.0"
-
-[package.extras]
-all = ["colorama (>=0.4.3,<0.5.0)", "rich (>=10.11.0,<13.0.0)", "shellingham (>=1.3.0,<2.0.0)"]
-dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"]
-doc = ["cairosvg (>=2.5.2,<3.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pillow (>=9.3.0,<10.0.0)"]
-test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<8.0.0)", "pytest-cov (>=2.10.0,<5.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<4.0.0)", "rich (>=10.11.0,<13.0.0)", "shellingham (>=1.3.0,<2.0.0)"]
+click = ">=8.0.0"
+rich = ">=10.11.0"
+shellingham = ">=1.3.0"
+typing-extensions = ">=3.7.4.3"
[[package]]
name = "typing-extensions"
-version = "4.10.0"
+version = "4.12.0"
description = "Backported and Experimental Type Hints for Python 3.8+"
optional = false
python-versions = ">=3.8"
files = [
- {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"},
- {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"},
+ {file = "typing_extensions-4.12.0-py3-none-any.whl", hash = "sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594"},
+ {file = "typing_extensions-4.12.0.tar.gz", hash = "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8"},
]
[[package]]
@@ -3129,32 +3183,119 @@ files = [
[package.extras]
test = ["coverage", "pytest", "pytest-cov"]
+[[package]]
+name = "ujson"
+version = "5.10.0"
+description = "Ultra fast JSON encoder and decoder for Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "ujson-5.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2601aa9ecdbee1118a1c2065323bda35e2c5a2cf0797ef4522d485f9d3ef65bd"},
+ {file = "ujson-5.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:348898dd702fc1c4f1051bc3aacbf894caa0927fe2c53e68679c073375f732cf"},
+ {file = "ujson-5.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22cffecf73391e8abd65ef5f4e4dd523162a3399d5e84faa6aebbf9583df86d6"},
+ {file = "ujson-5.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26b0e2d2366543c1bb4fbd457446f00b0187a2bddf93148ac2da07a53fe51569"},
+ {file = "ujson-5.10.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:caf270c6dba1be7a41125cd1e4fc7ba384bf564650beef0df2dd21a00b7f5770"},
+ {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a245d59f2ffe750446292b0094244df163c3dc96b3ce152a2c837a44e7cda9d1"},
+ {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:94a87f6e151c5f483d7d54ceef83b45d3a9cca7a9cb453dbdbb3f5a6f64033f5"},
+ {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:29b443c4c0a113bcbb792c88bea67b675c7ca3ca80c3474784e08bba01c18d51"},
+ {file = "ujson-5.10.0-cp310-cp310-win32.whl", hash = "sha256:c18610b9ccd2874950faf474692deee4223a994251bc0a083c114671b64e6518"},
+ {file = "ujson-5.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:924f7318c31874d6bb44d9ee1900167ca32aa9b69389b98ecbde34c1698a250f"},
+ {file = "ujson-5.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a5b366812c90e69d0f379a53648be10a5db38f9d4ad212b60af00bd4048d0f00"},
+ {file = "ujson-5.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:502bf475781e8167f0f9d0e41cd32879d120a524b22358e7f205294224c71126"},
+ {file = "ujson-5.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b91b5d0d9d283e085e821651184a647699430705b15bf274c7896f23fe9c9d8"},
+ {file = "ujson-5.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:129e39af3a6d85b9c26d5577169c21d53821d8cf68e079060602e861c6e5da1b"},
+ {file = "ujson-5.10.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f77b74475c462cb8b88680471193064d3e715c7c6074b1c8c412cb526466efe9"},
+ {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7ec0ca8c415e81aa4123501fee7f761abf4b7f386aad348501a26940beb1860f"},
+ {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab13a2a9e0b2865a6c6db9271f4b46af1c7476bfd51af1f64585e919b7c07fd4"},
+ {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:57aaf98b92d72fc70886b5a0e1a1ca52c2320377360341715dd3933a18e827b1"},
+ {file = "ujson-5.10.0-cp311-cp311-win32.whl", hash = "sha256:2987713a490ceb27edff77fb184ed09acdc565db700ee852823c3dc3cffe455f"},
+ {file = "ujson-5.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:f00ea7e00447918ee0eff2422c4add4c5752b1b60e88fcb3c067d4a21049a720"},
+ {file = "ujson-5.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98ba15d8cbc481ce55695beee9f063189dce91a4b08bc1d03e7f0152cd4bbdd5"},
+ {file = "ujson-5.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9d2edbf1556e4f56e50fab7d8ff993dbad7f54bac68eacdd27a8f55f433578e"},
+ {file = "ujson-5.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6627029ae4f52d0e1a2451768c2c37c0c814ffc04f796eb36244cf16b8e57043"},
+ {file = "ujson-5.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8ccb77b3e40b151e20519c6ae6d89bfe3f4c14e8e210d910287f778368bb3d1"},
+ {file = "ujson-5.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3caf9cd64abfeb11a3b661329085c5e167abbe15256b3b68cb5d914ba7396f3"},
+ {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6e32abdce572e3a8c3d02c886c704a38a1b015a1fb858004e03d20ca7cecbb21"},
+ {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a65b6af4d903103ee7b6f4f5b85f1bfd0c90ba4eeac6421aae436c9988aa64a2"},
+ {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:604a046d966457b6cdcacc5aa2ec5314f0e8c42bae52842c1e6fa02ea4bda42e"},
+ {file = "ujson-5.10.0-cp312-cp312-win32.whl", hash = "sha256:6dea1c8b4fc921bf78a8ff00bbd2bfe166345f5536c510671bccececb187c80e"},
+ {file = "ujson-5.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:38665e7d8290188b1e0d57d584eb8110951a9591363316dd41cf8686ab1d0abc"},
+ {file = "ujson-5.10.0-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:618efd84dc1acbd6bff8eaa736bb6c074bfa8b8a98f55b61c38d4ca2c1f7f287"},
+ {file = "ujson-5.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:38d5d36b4aedfe81dfe251f76c0467399d575d1395a1755de391e58985ab1c2e"},
+ {file = "ujson-5.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67079b1f9fb29ed9a2914acf4ef6c02844b3153913eb735d4bf287ee1db6e557"},
+ {file = "ujson-5.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7d0e0ceeb8fe2468c70ec0c37b439dd554e2aa539a8a56365fd761edb418988"},
+ {file = "ujson-5.10.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:59e02cd37bc7c44d587a0ba45347cc815fb7a5fe48de16bf05caa5f7d0d2e816"},
+ {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a890b706b64e0065f02577bf6d8ca3b66c11a5e81fb75d757233a38c07a1f20"},
+ {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:621e34b4632c740ecb491efc7f1fcb4f74b48ddb55e65221995e74e2d00bbff0"},
+ {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b9500e61fce0cfc86168b248104e954fead61f9be213087153d272e817ec7b4f"},
+ {file = "ujson-5.10.0-cp313-cp313-win32.whl", hash = "sha256:4c4fc16f11ac1612f05b6f5781b384716719547e142cfd67b65d035bd85af165"},
+ {file = "ujson-5.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:4573fd1695932d4f619928fd09d5d03d917274381649ade4328091ceca175539"},
+ {file = "ujson-5.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a984a3131da7f07563057db1c3020b1350a3e27a8ec46ccbfbf21e5928a43050"},
+ {file = "ujson-5.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:73814cd1b9db6fc3270e9d8fe3b19f9f89e78ee9d71e8bd6c9a626aeaeaf16bd"},
+ {file = "ujson-5.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61e1591ed9376e5eddda202ec229eddc56c612b61ac6ad07f96b91460bb6c2fb"},
+ {file = "ujson-5.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2c75269f8205b2690db4572a4a36fe47cd1338e4368bc73a7a0e48789e2e35a"},
+ {file = "ujson-5.10.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7223f41e5bf1f919cd8d073e35b229295aa8e0f7b5de07ed1c8fddac63a6bc5d"},
+ {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d4dc2fd6b3067c0782e7002ac3b38cf48608ee6366ff176bbd02cf969c9c20fe"},
+ {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:232cc85f8ee3c454c115455195a205074a56ff42608fd6b942aa4c378ac14dd7"},
+ {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cc6139531f13148055d691e442e4bc6601f6dba1e6d521b1585d4788ab0bfad4"},
+ {file = "ujson-5.10.0-cp38-cp38-win32.whl", hash = "sha256:e7ce306a42b6b93ca47ac4a3b96683ca554f6d35dd8adc5acfcd55096c8dfcb8"},
+ {file = "ujson-5.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:e82d4bb2138ab05e18f089a83b6564fee28048771eb63cdecf4b9b549de8a2cc"},
+ {file = "ujson-5.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dfef2814c6b3291c3c5f10065f745a1307d86019dbd7ea50e83504950136ed5b"},
+ {file = "ujson-5.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4734ee0745d5928d0ba3a213647f1c4a74a2a28edc6d27b2d6d5bd9fa4319e27"},
+ {file = "ujson-5.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d47ebb01bd865fdea43da56254a3930a413f0c5590372a1241514abae8aa7c76"},
+ {file = "ujson-5.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dee5e97c2496874acbf1d3e37b521dd1f307349ed955e62d1d2f05382bc36dd5"},
+ {file = "ujson-5.10.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7490655a2272a2d0b072ef16b0b58ee462f4973a8f6bbe64917ce5e0a256f9c0"},
+ {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba17799fcddaddf5c1f75a4ba3fd6441f6a4f1e9173f8a786b42450851bd74f1"},
+ {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2aff2985cef314f21d0fecc56027505804bc78802c0121343874741650a4d3d1"},
+ {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ad88ac75c432674d05b61184178635d44901eb749786c8eb08c102330e6e8996"},
+ {file = "ujson-5.10.0-cp39-cp39-win32.whl", hash = "sha256:2544912a71da4ff8c4f7ab5606f947d7299971bdd25a45e008e467ca638d13c9"},
+ {file = "ujson-5.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:3ff201d62b1b177a46f113bb43ad300b424b7847f9c5d38b1b4ad8f75d4a282a"},
+ {file = "ujson-5.10.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5b6fee72fa77dc172a28f21693f64d93166534c263adb3f96c413ccc85ef6e64"},
+ {file = "ujson-5.10.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:61d0af13a9af01d9f26d2331ce49bb5ac1fb9c814964018ac8df605b5422dcb3"},
+ {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecb24f0bdd899d368b715c9e6664166cf694d1e57be73f17759573a6986dd95a"},
+ {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fbd8fd427f57a03cff3ad6574b5e299131585d9727c8c366da4624a9069ed746"},
+ {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beeaf1c48e32f07d8820c705ff8e645f8afa690cca1544adba4ebfa067efdc88"},
+ {file = "ujson-5.10.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:baed37ea46d756aca2955e99525cc02d9181de67f25515c468856c38d52b5f3b"},
+ {file = "ujson-5.10.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7663960f08cd5a2bb152f5ee3992e1af7690a64c0e26d31ba7b3ff5b2ee66337"},
+ {file = "ujson-5.10.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:d8640fb4072d36b08e95a3a380ba65779d356b2fee8696afeb7794cf0902d0a1"},
+ {file = "ujson-5.10.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78778a3aa7aafb11e7ddca4e29f46bc5139131037ad628cc10936764282d6753"},
+ {file = "ujson-5.10.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0111b27f2d5c820e7f2dbad7d48e3338c824e7ac4d2a12da3dc6061cc39c8e6"},
+ {file = "ujson-5.10.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:c66962ca7565605b355a9ed478292da628b8f18c0f2793021ca4425abf8b01e5"},
+ {file = "ujson-5.10.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ba43cc34cce49cf2d4bc76401a754a81202d8aa926d0e2b79f0ee258cb15d3a4"},
+ {file = "ujson-5.10.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ac56eb983edce27e7f51d05bc8dd820586c6e6be1c5216a6809b0c668bb312b8"},
+ {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44bd4b23a0e723bf8b10628288c2c7c335161d6840013d4d5de20e48551773b"},
+ {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c10f4654e5326ec14a46bcdeb2b685d4ada6911050aa8baaf3501e57024b804"},
+ {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0de4971a89a762398006e844ae394bd46991f7c385d7a6a3b93ba229e6dac17e"},
+ {file = "ujson-5.10.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e1402f0564a97d2a52310ae10a64d25bcef94f8dd643fcf5d310219d915484f7"},
+ {file = "ujson-5.10.0.tar.gz", hash = "sha256:b3cd8f3c5d8c7738257f1018880444f7b7d9b66232c64649f562d7ba86ad4bc1"},
+]
+
[[package]]
name = "urllib3"
-version = "2.0.7"
+version = "2.2.1"
description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"},
- {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"},
+ {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"},
+ {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"},
]
[package.extras]
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
-secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"]
+h2 = ["h2 (>=4,<5)"]
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
zstd = ["zstandard (>=0.18.0)"]
[[package]]
name = "uvicorn"
-version = "0.27.1"
+version = "0.30.0"
description = "The lightning-fast ASGI server."
optional = false
python-versions = ">=3.8"
files = [
- {file = "uvicorn-0.27.1-py3-none-any.whl", hash = "sha256:5c89da2f3895767472a35556e539fd59f7edbe9b1e9c0e1c99eebeadc61838e4"},
- {file = "uvicorn-0.27.1.tar.gz", hash = "sha256:3d9a267296243532db80c83a959a3400502165ade2c1338dea4e67915fd4745a"},
+ {file = "uvicorn-0.30.0-py3-none-any.whl", hash = "sha256:78fa0b5f56abb8562024a59041caeb555c86e48d0efdd23c3fe7de7a4075bdab"},
+ {file = "uvicorn-0.30.0.tar.gz", hash = "sha256:f678dec4fa3a39706bbf49b9ec5fc40049d42418716cea52b53f07828a60aa37"},
]
[package.dependencies]
@@ -3217,13 +3358,13 @@ test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)"
[[package]]
name = "virtualenv"
-version = "20.25.1"
+version = "20.26.2"
description = "Virtual Python Environment builder"
optional = false
python-versions = ">=3.7"
files = [
- {file = "virtualenv-20.25.1-py3-none-any.whl", hash = "sha256:961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a"},
- {file = "virtualenv-20.25.1.tar.gz", hash = "sha256:e08e13ecdca7a0bd53798f356d5831434afa5b07b93f0abdf0797b7a06ffe197"},
+ {file = "virtualenv-20.26.2-py3-none-any.whl", hash = "sha256:a624db5e94f01ad993d476b9ee5346fdf7b9de43ccaee0e0197012dc838a0e9b"},
+ {file = "virtualenv-20.26.2.tar.gz", hash = "sha256:82bf0f4eebbb78d36ddaee0283d43fe5736b53880b8a8cdcd37390a07ac3741c"},
]
[package.dependencies]
@@ -3232,91 +3373,91 @@ filelock = ">=3.12.2,<4"
platformdirs = ">=3.9.1,<5"
[package.extras]
-docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
+docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"]
[[package]]
name = "watchfiles"
-version = "0.21.0"
+version = "0.22.0"
description = "Simple, modern and high performance file watching and code reload in python."
optional = false
python-versions = ">=3.8"
files = [
- {file = "watchfiles-0.21.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:27b4035013f1ea49c6c0b42d983133b136637a527e48c132d368eb19bf1ac6aa"},
- {file = "watchfiles-0.21.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c81818595eff6e92535ff32825f31c116f867f64ff8cdf6562cd1d6b2e1e8f3e"},
- {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6c107ea3cf2bd07199d66f156e3ea756d1b84dfd43b542b2d870b77868c98c03"},
- {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d9ac347653ebd95839a7c607608703b20bc07e577e870d824fa4801bc1cb124"},
- {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5eb86c6acb498208e7663ca22dbe68ca2cf42ab5bf1c776670a50919a56e64ab"},
- {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f564bf68404144ea6b87a78a3f910cc8de216c6b12a4cf0b27718bf4ec38d303"},
- {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d0f32ebfaa9c6011f8454994f86108c2eb9c79b8b7de00b36d558cadcedaa3d"},
- {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6d45d9b699ecbac6c7bd8e0a2609767491540403610962968d258fd6405c17c"},
- {file = "watchfiles-0.21.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:aff06b2cac3ef4616e26ba17a9c250c1fe9dd8a5d907d0193f84c499b1b6e6a9"},
- {file = "watchfiles-0.21.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d9792dff410f266051025ecfaa927078b94cc7478954b06796a9756ccc7e14a9"},
- {file = "watchfiles-0.21.0-cp310-none-win32.whl", hash = "sha256:214cee7f9e09150d4fb42e24919a1e74d8c9b8a9306ed1474ecaddcd5479c293"},
- {file = "watchfiles-0.21.0-cp310-none-win_amd64.whl", hash = "sha256:1ad7247d79f9f55bb25ab1778fd47f32d70cf36053941f07de0b7c4e96b5d235"},
- {file = "watchfiles-0.21.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:668c265d90de8ae914f860d3eeb164534ba2e836811f91fecc7050416ee70aa7"},
- {file = "watchfiles-0.21.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a23092a992e61c3a6a70f350a56db7197242f3490da9c87b500f389b2d01eef"},
- {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e7941bbcfdded9c26b0bf720cb7e6fd803d95a55d2c14b4bd1f6a2772230c586"},
- {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11cd0c3100e2233e9c53106265da31d574355c288e15259c0d40a4405cbae317"},
- {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d78f30cbe8b2ce770160d3c08cff01b2ae9306fe66ce899b73f0409dc1846c1b"},
- {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6674b00b9756b0af620aa2a3346b01f8e2a3dc729d25617e1b89cf6af4a54eb1"},
- {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fd7ac678b92b29ba630d8c842d8ad6c555abda1b9ef044d6cc092dacbfc9719d"},
- {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c873345680c1b87f1e09e0eaf8cf6c891b9851d8b4d3645e7efe2ec20a20cc7"},
- {file = "watchfiles-0.21.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:49f56e6ecc2503e7dbe233fa328b2be1a7797d31548e7a193237dcdf1ad0eee0"},
- {file = "watchfiles-0.21.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:02d91cbac553a3ad141db016e3350b03184deaafeba09b9d6439826ee594b365"},
- {file = "watchfiles-0.21.0-cp311-none-win32.whl", hash = "sha256:ebe684d7d26239e23d102a2bad2a358dedf18e462e8808778703427d1f584400"},
- {file = "watchfiles-0.21.0-cp311-none-win_amd64.whl", hash = "sha256:4566006aa44cb0d21b8ab53baf4b9c667a0ed23efe4aaad8c227bfba0bf15cbe"},
- {file = "watchfiles-0.21.0-cp311-none-win_arm64.whl", hash = "sha256:c550a56bf209a3d987d5a975cdf2063b3389a5d16caf29db4bdddeae49f22078"},
- {file = "watchfiles-0.21.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:51ddac60b96a42c15d24fbdc7a4bfcd02b5a29c047b7f8bf63d3f6f5a860949a"},
- {file = "watchfiles-0.21.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:511f0b034120cd1989932bf1e9081aa9fb00f1f949fbd2d9cab6264916ae89b1"},
- {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cfb92d49dbb95ec7a07511bc9efb0faff8fe24ef3805662b8d6808ba8409a71a"},
- {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f92944efc564867bbf841c823c8b71bb0be75e06b8ce45c084b46411475a915"},
- {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:642d66b75eda909fd1112d35c53816d59789a4b38c141a96d62f50a3ef9b3360"},
- {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d23bcd6c8eaa6324fe109d8cac01b41fe9a54b8c498af9ce464c1aeeb99903d6"},
- {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18d5b4da8cf3e41895b34e8c37d13c9ed294954907929aacd95153508d5d89d7"},
- {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b8d1eae0f65441963d805f766c7e9cd092f91e0c600c820c764a4ff71a0764c"},
- {file = "watchfiles-0.21.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1fd9a5205139f3c6bb60d11f6072e0552f0a20b712c85f43d42342d162be1235"},
- {file = "watchfiles-0.21.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a1e3014a625bcf107fbf38eece0e47fa0190e52e45dc6eee5a8265ddc6dc5ea7"},
- {file = "watchfiles-0.21.0-cp312-none-win32.whl", hash = "sha256:9d09869f2c5a6f2d9df50ce3064b3391d3ecb6dced708ad64467b9e4f2c9bef3"},
- {file = "watchfiles-0.21.0-cp312-none-win_amd64.whl", hash = "sha256:18722b50783b5e30a18a8a5db3006bab146d2b705c92eb9a94f78c72beb94094"},
- {file = "watchfiles-0.21.0-cp312-none-win_arm64.whl", hash = "sha256:a3b9bec9579a15fb3ca2d9878deae789df72f2b0fdaf90ad49ee389cad5edab6"},
- {file = "watchfiles-0.21.0-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:4ea10a29aa5de67de02256a28d1bf53d21322295cb00bd2d57fcd19b850ebd99"},
- {file = "watchfiles-0.21.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:40bca549fdc929b470dd1dbfcb47b3295cb46a6d2c90e50588b0a1b3bd98f429"},
- {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9b37a7ba223b2f26122c148bb8d09a9ff312afca998c48c725ff5a0a632145f7"},
- {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec8c8900dc5c83650a63dd48c4d1d245343f904c4b64b48798c67a3767d7e165"},
- {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8ad3fe0a3567c2f0f629d800409cd528cb6251da12e81a1f765e5c5345fd0137"},
- {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d353c4cfda586db2a176ce42c88f2fc31ec25e50212650c89fdd0f560ee507b"},
- {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:83a696da8922314ff2aec02987eefb03784f473281d740bf9170181829133765"},
- {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a03651352fc20975ee2a707cd2d74a386cd303cc688f407296064ad1e6d1562"},
- {file = "watchfiles-0.21.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3ad692bc7792be8c32918c699638b660c0de078a6cbe464c46e1340dadb94c19"},
- {file = "watchfiles-0.21.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06247538e8253975bdb328e7683f8515ff5ff041f43be6c40bff62d989b7d0b0"},
- {file = "watchfiles-0.21.0-cp38-none-win32.whl", hash = "sha256:9a0aa47f94ea9a0b39dd30850b0adf2e1cd32a8b4f9c7aa443d852aacf9ca214"},
- {file = "watchfiles-0.21.0-cp38-none-win_amd64.whl", hash = "sha256:8d5f400326840934e3507701f9f7269247f7c026d1b6cfd49477d2be0933cfca"},
- {file = "watchfiles-0.21.0-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:7f762a1a85a12cc3484f77eee7be87b10f8c50b0b787bb02f4e357403cad0c0e"},
- {file = "watchfiles-0.21.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6e9be3ef84e2bb9710f3f777accce25556f4a71e15d2b73223788d528fcc2052"},
- {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4c48a10d17571d1275701e14a601e36959ffada3add8cdbc9e5061a6e3579a5d"},
- {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c889025f59884423428c261f212e04d438de865beda0b1e1babab85ef4c0f01"},
- {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:66fac0c238ab9a2e72d026b5fb91cb902c146202bbd29a9a1a44e8db7b710b6f"},
- {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b4a21f71885aa2744719459951819e7bf5a906a6448a6b2bbce8e9cc9f2c8128"},
- {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c9198c989f47898b2c22201756f73249de3748e0fc9de44adaf54a8b259cc0c"},
- {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f57c4461cd24fda22493109c45b3980863c58a25b8bec885ca8bea6b8d4b28"},
- {file = "watchfiles-0.21.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:853853cbf7bf9408b404754b92512ebe3e3a83587503d766d23e6bf83d092ee6"},
- {file = "watchfiles-0.21.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d5b1dc0e708fad9f92c296ab2f948af403bf201db8fb2eb4c8179db143732e49"},
- {file = "watchfiles-0.21.0-cp39-none-win32.whl", hash = "sha256:59137c0c6826bd56c710d1d2bda81553b5e6b7c84d5a676747d80caf0409ad94"},
- {file = "watchfiles-0.21.0-cp39-none-win_amd64.whl", hash = "sha256:6cb8fdc044909e2078c248986f2fc76f911f72b51ea4a4fbbf472e01d14faa58"},
- {file = "watchfiles-0.21.0-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:ab03a90b305d2588e8352168e8c5a1520b721d2d367f31e9332c4235b30b8994"},
- {file = "watchfiles-0.21.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:927c589500f9f41e370b0125c12ac9e7d3a2fd166b89e9ee2828b3dda20bfe6f"},
- {file = "watchfiles-0.21.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bd467213195e76f838caf2c28cd65e58302d0254e636e7c0fca81efa4a2e62c"},
- {file = "watchfiles-0.21.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02b73130687bc3f6bb79d8a170959042eb56eb3a42df3671c79b428cd73f17cc"},
- {file = "watchfiles-0.21.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:08dca260e85ffae975448e344834d765983237ad6dc308231aa16e7933db763e"},
- {file = "watchfiles-0.21.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:3ccceb50c611c433145502735e0370877cced72a6c70fd2410238bcbc7fe51d8"},
- {file = "watchfiles-0.21.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57d430f5fb63fea141ab71ca9c064e80de3a20b427ca2febcbfcef70ff0ce895"},
- {file = "watchfiles-0.21.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dd5fad9b9c0dd89904bbdea978ce89a2b692a7ee8a0ce19b940e538c88a809c"},
- {file = "watchfiles-0.21.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:be6dd5d52b73018b21adc1c5d28ac0c68184a64769052dfeb0c5d9998e7f56a2"},
- {file = "watchfiles-0.21.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b3cab0e06143768499384a8a5efb9c4dc53e19382952859e4802f294214f36ec"},
- {file = "watchfiles-0.21.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c6ed10c2497e5fedadf61e465b3ca12a19f96004c15dcffe4bd442ebadc2d85"},
- {file = "watchfiles-0.21.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43babacef21c519bc6631c5fce2a61eccdfc011b4bcb9047255e9620732c8097"},
- {file = "watchfiles-0.21.0.tar.gz", hash = "sha256:c76c635fabf542bb78524905718c39f736a98e5ab25b23ec6d4abede1a85a6a3"},
+ {file = "watchfiles-0.22.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:da1e0a8caebf17976e2ffd00fa15f258e14749db5e014660f53114b676e68538"},
+ {file = "watchfiles-0.22.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61af9efa0733dc4ca462347becb82e8ef4945aba5135b1638bfc20fad64d4f0e"},
+ {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d9188979a58a096b6f8090e816ccc3f255f137a009dd4bbec628e27696d67c1"},
+ {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2bdadf6b90c099ca079d468f976fd50062905d61fae183f769637cb0f68ba59a"},
+ {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:067dea90c43bf837d41e72e546196e674f68c23702d3ef80e4e816937b0a3ffd"},
+ {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbf8a20266136507abf88b0df2328e6a9a7c7309e8daff124dda3803306a9fdb"},
+ {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1235c11510ea557fe21be5d0e354bae2c655a8ee6519c94617fe63e05bca4171"},
+ {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2444dc7cb9d8cc5ab88ebe792a8d75709d96eeef47f4c8fccb6df7c7bc5be71"},
+ {file = "watchfiles-0.22.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c5af2347d17ab0bd59366db8752d9e037982e259cacb2ba06f2c41c08af02c39"},
+ {file = "watchfiles-0.22.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9624a68b96c878c10437199d9a8b7d7e542feddda8d5ecff58fdc8e67b460848"},
+ {file = "watchfiles-0.22.0-cp310-none-win32.whl", hash = "sha256:4b9f2a128a32a2c273d63eb1fdbf49ad64852fc38d15b34eaa3f7ca2f0d2b797"},
+ {file = "watchfiles-0.22.0-cp310-none-win_amd64.whl", hash = "sha256:2627a91e8110b8de2406d8b2474427c86f5a62bf7d9ab3654f541f319ef22bcb"},
+ {file = "watchfiles-0.22.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8c39987a1397a877217be1ac0fb1d8b9f662c6077b90ff3de2c05f235e6a8f96"},
+ {file = "watchfiles-0.22.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a927b3034d0672f62fb2ef7ea3c9fc76d063c4b15ea852d1db2dc75fe2c09696"},
+ {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:052d668a167e9fc345c24203b104c313c86654dd6c0feb4b8a6dfc2462239249"},
+ {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e45fb0d70dda1623a7045bd00c9e036e6f1f6a85e4ef2c8ae602b1dfadf7550"},
+ {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c49b76a78c156979759d759339fb62eb0549515acfe4fd18bb151cc07366629c"},
+ {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4a65474fd2b4c63e2c18ac67a0c6c66b82f4e73e2e4d940f837ed3d2fd9d4da"},
+ {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc0cba54f47c660d9fa3218158b8963c517ed23bd9f45fe463f08262a4adae1"},
+ {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94ebe84a035993bb7668f58a0ebf998174fb723a39e4ef9fce95baabb42b787f"},
+ {file = "watchfiles-0.22.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e0f0a874231e2839abbf473256efffe577d6ee2e3bfa5b540479e892e47c172d"},
+ {file = "watchfiles-0.22.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:213792c2cd3150b903e6e7884d40660e0bcec4465e00563a5fc03f30ea9c166c"},
+ {file = "watchfiles-0.22.0-cp311-none-win32.whl", hash = "sha256:b44b70850f0073b5fcc0b31ede8b4e736860d70e2dbf55701e05d3227a154a67"},
+ {file = "watchfiles-0.22.0-cp311-none-win_amd64.whl", hash = "sha256:00f39592cdd124b4ec5ed0b1edfae091567c72c7da1487ae645426d1b0ffcad1"},
+ {file = "watchfiles-0.22.0-cp311-none-win_arm64.whl", hash = "sha256:3218a6f908f6a276941422b035b511b6d0d8328edd89a53ae8c65be139073f84"},
+ {file = "watchfiles-0.22.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:c7b978c384e29d6c7372209cbf421d82286a807bbcdeb315427687f8371c340a"},
+ {file = "watchfiles-0.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bd4c06100bce70a20c4b81e599e5886cf504c9532951df65ad1133e508bf20be"},
+ {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:425440e55cd735386ec7925f64d5dde392e69979d4c8459f6bb4e920210407f2"},
+ {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:68fe0c4d22332d7ce53ad094622b27e67440dacefbaedd29e0794d26e247280c"},
+ {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a8a31bfd98f846c3c284ba694c6365620b637debdd36e46e1859c897123aa232"},
+ {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc2e8fe41f3cac0660197d95216c42910c2b7e9c70d48e6d84e22f577d106fc1"},
+ {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b7cc10261c2786c41d9207193a85c1db1b725cf87936df40972aab466179b6"},
+ {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28585744c931576e535860eaf3f2c0ec7deb68e3b9c5a85ca566d69d36d8dd27"},
+ {file = "watchfiles-0.22.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:00095dd368f73f8f1c3a7982a9801190cc88a2f3582dd395b289294f8975172b"},
+ {file = "watchfiles-0.22.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:52fc9b0dbf54d43301a19b236b4a4614e610605f95e8c3f0f65c3a456ffd7d35"},
+ {file = "watchfiles-0.22.0-cp312-none-win32.whl", hash = "sha256:581f0a051ba7bafd03e17127735d92f4d286af941dacf94bcf823b101366249e"},
+ {file = "watchfiles-0.22.0-cp312-none-win_amd64.whl", hash = "sha256:aec83c3ba24c723eac14225194b862af176d52292d271c98820199110e31141e"},
+ {file = "watchfiles-0.22.0-cp312-none-win_arm64.whl", hash = "sha256:c668228833c5619f6618699a2c12be057711b0ea6396aeaece4ded94184304ea"},
+ {file = "watchfiles-0.22.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d47e9ef1a94cc7a536039e46738e17cce058ac1593b2eccdede8bf72e45f372a"},
+ {file = "watchfiles-0.22.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:28f393c1194b6eaadcdd8f941307fc9bbd7eb567995232c830f6aef38e8a6e88"},
+ {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd64f3a4db121bc161644c9e10a9acdb836853155a108c2446db2f5ae1778c3d"},
+ {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2abeb79209630da981f8ebca30a2c84b4c3516a214451bfc5f106723c5f45843"},
+ {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4cc382083afba7918e32d5ef12321421ef43d685b9a67cc452a6e6e18920890e"},
+ {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d048ad5d25b363ba1d19f92dcf29023988524bee6f9d952130b316c5802069cb"},
+ {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:103622865599f8082f03af4214eaff90e2426edff5e8522c8f9e93dc17caee13"},
+ {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3e1f3cf81f1f823e7874ae563457828e940d75573c8fbf0ee66818c8b6a9099"},
+ {file = "watchfiles-0.22.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8597b6f9dc410bdafc8bb362dac1cbc9b4684a8310e16b1ff5eee8725d13dcd6"},
+ {file = "watchfiles-0.22.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0b04a2cbc30e110303baa6d3ddce8ca3664bc3403be0f0ad513d1843a41c97d1"},
+ {file = "watchfiles-0.22.0-cp38-none-win32.whl", hash = "sha256:b610fb5e27825b570554d01cec427b6620ce9bd21ff8ab775fc3a32f28bba63e"},
+ {file = "watchfiles-0.22.0-cp38-none-win_amd64.whl", hash = "sha256:fe82d13461418ca5e5a808a9e40f79c1879351fcaeddbede094028e74d836e86"},
+ {file = "watchfiles-0.22.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:3973145235a38f73c61474d56ad6199124e7488822f3a4fc97c72009751ae3b0"},
+ {file = "watchfiles-0.22.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:280a4afbc607cdfc9571b9904b03a478fc9f08bbeec382d648181c695648202f"},
+ {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a0d883351a34c01bd53cfa75cd0292e3f7e268bacf2f9e33af4ecede7e21d1d"},
+ {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9165bcab15f2b6d90eedc5c20a7f8a03156b3773e5fb06a790b54ccecdb73385"},
+ {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc1b9b56f051209be458b87edb6856a449ad3f803315d87b2da4c93b43a6fe72"},
+ {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dc1fc25a1dedf2dd952909c8e5cb210791e5f2d9bc5e0e8ebc28dd42fed7562"},
+ {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dc92d2d2706d2b862ce0568b24987eba51e17e14b79a1abcd2edc39e48e743c8"},
+ {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97b94e14b88409c58cdf4a8eaf0e67dfd3ece7e9ce7140ea6ff48b0407a593ec"},
+ {file = "watchfiles-0.22.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:96eec15e5ea7c0b6eb5bfffe990fc7c6bd833acf7e26704eb18387fb2f5fd087"},
+ {file = "watchfiles-0.22.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:28324d6b28bcb8d7c1041648d7b63be07a16db5510bea923fc80b91a2a6cbed6"},
+ {file = "watchfiles-0.22.0-cp39-none-win32.whl", hash = "sha256:8c3e3675e6e39dc59b8fe5c914a19d30029e36e9f99468dddffd432d8a7b1c93"},
+ {file = "watchfiles-0.22.0-cp39-none-win_amd64.whl", hash = "sha256:25c817ff2a86bc3de3ed2df1703e3d24ce03479b27bb4527c57e722f8554d971"},
+ {file = "watchfiles-0.22.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b810a2c7878cbdecca12feae2c2ae8af59bea016a78bc353c184fa1e09f76b68"},
+ {file = "watchfiles-0.22.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f7e1f9c5d1160d03b93fc4b68a0aeb82fe25563e12fbcdc8507f8434ab6f823c"},
+ {file = "watchfiles-0.22.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:030bc4e68d14bcad2294ff68c1ed87215fbd9a10d9dea74e7cfe8a17869785ab"},
+ {file = "watchfiles-0.22.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ace7d060432acde5532e26863e897ee684780337afb775107c0a90ae8dbccfd2"},
+ {file = "watchfiles-0.22.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5834e1f8b71476a26df97d121c0c0ed3549d869124ed2433e02491553cb468c2"},
+ {file = "watchfiles-0.22.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:0bc3b2f93a140df6806c8467c7f51ed5e55a931b031b5c2d7ff6132292e803d6"},
+ {file = "watchfiles-0.22.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8fdebb655bb1ba0122402352b0a4254812717a017d2dc49372a1d47e24073795"},
+ {file = "watchfiles-0.22.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c8e0aa0e8cc2a43561e0184c0513e291ca891db13a269d8d47cb9841ced7c71"},
+ {file = "watchfiles-0.22.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2f350cbaa4bb812314af5dab0eb8d538481e2e2279472890864547f3fe2281ed"},
+ {file = "watchfiles-0.22.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7a74436c415843af2a769b36bf043b6ccbc0f8d784814ba3d42fc961cdb0a9dc"},
+ {file = "watchfiles-0.22.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00ad0bcd399503a84cc688590cdffbe7a991691314dde5b57b3ed50a41319a31"},
+ {file = "watchfiles-0.22.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72a44e9481afc7a5ee3291b09c419abab93b7e9c306c9ef9108cb76728ca58d2"},
+ {file = "watchfiles-0.22.0.tar.gz", hash = "sha256:988e981aaab4f3955209e7e28c7794acdb690be1efa7f16f8ea5aba7ffdadacb"},
]
[package.dependencies]
@@ -3324,26 +3465,24 @@ anyio = ">=3.0.0"
[[package]]
name = "web3"
-version = "6.15.1"
-description = "web3.py"
+version = "7.0.0b6"
+description = "web3: A Python library for interacting with Ethereum"
optional = false
-python-versions = ">=3.7.2"
+python-versions = "<4,>=3.8"
files = [
- {file = "web3-6.15.1-py3-none-any.whl", hash = "sha256:4e4a8313aa4556ecde61c852a62405b853b667498b07da6ff05c29fe8c79096b"},
- {file = "web3-6.15.1.tar.gz", hash = "sha256:f9e7eefc1b3c3d194868a4ef9583b625c18ea3f31a48ebe143183db74898f381"},
+ {file = "web3-7.0.0b6-py3-none-any.whl", hash = "sha256:96c424f93df2d543d64cbe1758d2a95191e925579f503023d4fd6479d449a5ed"},
+ {file = "web3-7.0.0b6.tar.gz", hash = "sha256:2e33398652c274f35e2cd432327a58a03cd233bb0721c11e4b95687a6faccd2f"},
]
[package.dependencies]
aiohttp = ">=3.7.4.post0"
-eth-abi = ">=4.0.0"
-eth-account = ">=0.8.0"
+eth-abi = ">=5.0.1"
+eth-account = ">=0.12.2"
eth-hash = {version = ">=0.5.1", extras = ["pycryptodome"]}
-eth-typing = ">=3.0.0"
-eth-utils = ">=2.1.0"
-hexbytes = ">=0.1.0,<0.4.0"
-jsonschema = ">=4.0.0"
-lru-dict = ">=1.1.6,<1.3.0"
-protobuf = ">=4.21.6"
+eth-typing = ">=4.0.0"
+eth-utils = ">=4.0.0"
+hexbytes = ">=1.2.0"
+pydantic = ">=2.4.0"
pyunormalize = ">=15.0.0"
pywin32 = {version = ">=223", markers = "platform_system == \"Windows\""}
requests = ">=2.16.0"
@@ -3351,11 +3490,9 @@ typing-extensions = ">=4.0.1"
websockets = ">=10.0.0"
[package.extras]
-dev = ["black (>=22.1.0)", "build (>=0.9.0)", "bumpversion", "eth-tester[py-evm] (==v0.9.1-b.2)", "flake8 (==3.8.3)", "flaky (>=3.7.0)", "hypothesis (>=3.31.2)", "importlib-metadata (<5.0)", "ipfshttpclient (==0.8.0a2)", "isort (>=5.11.0)", "mypy (==1.4.1)", "py-geth (>=3.14.0)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.18.1,<0.23)", "pytest-mock (>=1.10)", "pytest-watch (>=4.2)", "pytest-xdist (>=1.29)", "setuptools (>=38.6.0)", "sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=3.18.0)", "tqdm (>4.32)", "twine (>=1.13)", "types-protobuf (==3.19.13)", "types-requests (>=2.26.1)", "types-setuptools (>=57.4.4)", "when-changed (>=0.3.0)"]
-docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"]
-ipfs = ["ipfshttpclient (==0.8.0a2)"]
-linter = ["black (>=22.1.0)", "flake8 (==3.8.3)", "isort (>=5.11.0)", "mypy (==1.4.1)", "types-protobuf (==3.19.13)", "types-requests (>=2.26.1)", "types-setuptools (>=57.4.4)"]
-tester = ["eth-tester[py-evm] (==v0.9.1-b.2)", "py-geth (>=3.14.0)"]
+dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-tester[py-evm] (>=0.11.0b1,<0.12.0b1)", "flaky (>=3.7.0)", "hypothesis (>=3.31.2)", "ipython", "pre-commit (>=3.4.0)", "py-geth (>=4.1.0)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.18.1,<0.23)", "pytest-asyncio (>=0.21.2,<0.23)", "pytest-mock (>=1.10)", "pytest-xdist (>=2.4.0)", "setuptools (>=38.6.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "tqdm (>4.32)", "twine (>=1.13)", "wheel"]
+docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"]
+test = ["eth-tester[py-evm] (>=0.11.0b1,<0.12.0b1)", "py-geth (>=4.1.0)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.18.1,<0.23)", "pytest-mock (>=1.10)", "pytest-xdist (>=2.4.0)"]
[[package]]
name = "websockets"
@@ -3543,23 +3680,24 @@ multidict = ">=4.0"
[[package]]
name = "zipp"
-version = "3.17.0"
+version = "3.19.0"
description = "Backport of pathlib-compatible object wrapper for zip files"
optional = false
python-versions = ">=3.8"
files = [
- {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"},
- {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"},
+ {file = "zipp-3.19.0-py3-none-any.whl", hash = "sha256:96dc6ad62f1441bcaccef23b274ec471518daf4fbbc580341204936a5a3dddec"},
+ {file = "zipp-3.19.0.tar.gz", hash = "sha256:952df858fb3164426c976d9338d3961e8e8b3758e2e059e0f754b8c4262625ee"},
]
[package.extras]
-docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"]
-testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"]
+docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
+testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"]
[extras]
ibet-explorer = ["aiohttp", "async-cache", "ibet-prime-explorer", "textual", "typer"]
+settlement-cli = ["ibet-prime-settlement", "typer"]
[metadata]
lock-version = "2.0"
-python-versions = "3.11.2"
-content-hash = "832f492b0a4bc89eaf808bdf6080d50ff5dcb6a6fbb9bdf4cda00d2aedc7e05d"
+python-versions = "3.12.2"
+content-hash = "a3aa9da265176a0f230087f3eadd2880fcf610df97ff9915ed0f7a688f5f133c"
diff --git a/pyproject.toml b/pyproject.toml
index f55a6c68..04318d00 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,36 +1,42 @@
[tool.poetry]
name = "ibet-prime"
-version = "24.3"
+version = "24.6"
description = "ibet-Prime is an API service that enables the issuance and management of security tokens on the ibet network."
authors = ["BOOSTRY Co., Ltd. "]
license = "Apache License, Version 2.0"
readme = "README.md"
+[tool.poetry.scripts]
+ibet-explorer = "cmd.explorer.src:main"
+settlement-cli = "cmd.settlement.src:main"
+
[tool.poetry.dependencies]
-python = "3.11.2"
+python = "3.12.2"
alembic = "^1.13.1"
boto3 = "~1.34.59"
coincurve = "~19.0.1"
-eth-keyfile = "0.7.0"
-eth-utils = "~3.0.0"
-fastapi = "~0.110.0"
-gunicorn = "~21.2.0"
-orjson = "~3.9.15"
+eth-keyfile = "0.8.1"
+eth-utils = "~4.1.1"
+fastapi = "~0.111.0"
+gunicorn = "~22.0.0"
+orjson = "~3.10.3"
psycopg = {extras = ["c"], version = "^3.1.18"}
pycryptodome = "~3.20"
-pydantic = "~2.6.3"
+pydantic = "~2.7.1"
pytz = "~2024.1"
shared-memory-dict = "~0.7.2"
-web3 = "~6.15.1"
+web3 = "7.0.0b6"
httpx = "^0.27.0"
sqlalchemy = {extras = ["asyncio"], version = "^2.0.28"}
-uvicorn = {extras = ["standard"], version = "~0.27.0"}
+uvicorn = {extras = ["standard"], version = "~0.30.0"}
uvloop = "~0.19.0"
+memray = "^1.12.0"
ibet-prime-explorer = {path = "cmd/explorer", optional = true, develop = true}
+ibet-prime-settlement = {path = "cmd/settlement", optional = true, develop = true}
textual = {version = "~0.44.1", optional = true}
async-cache = {version = "~1.1.1", optional = true}
-typer = {version = "~0.7.0", optional = true}
+typer = "0.12.3"
aiohttp = {version = "~3.9.3", optional = true}
[tool.poetry.group.dev.dependencies]
@@ -39,13 +45,14 @@ pytest-cov = "^4.1.0"
pyyaml = "^6.0"
pre-commit = "^3.6.0"
isort = "^5.13.2"
-httpx = "^0.27.0"
black = "^24.1.1"
textual-dev = "^1.2.1"
pytest-alembic = "^0.10.7"
pytest-freezer = "^0.4.8"
pytest-asyncio = "0.23.3"
pytest-aiohttp = "^1.0.5"
+ruamel-yaml = "^0.18.6"
+pytest-memray = "^1.6.0"
[tool.poetry.extras]
ibet-explorer = [
@@ -55,6 +62,10 @@ ibet-explorer = [
"typer",
"aiohttp"
]
+settlement-cli = [
+ "ibet-prime-settlement",
+ "typer",
+]
[tool.isort]
profile = "black"
diff --git a/tests/Dockerfile_hardhat b/tests/Dockerfile_hardhat
new file mode 100644
index 00000000..043ebf19
--- /dev/null
+++ b/tests/Dockerfile_hardhat
@@ -0,0 +1,17 @@
+FROM node:20-alpine
+
+# Make directory
+RUN mkdir -p /hardhat
+
+# Copy files
+COPY package.json /hardhat
+COPY package-lock.json /hardhat
+COPY hardhat.config.js /hardhat
+
+WORKDIR /hardhat
+
+# Install hardhat
+RUN npm install --only=dev
+
+# Run hardhat node
+CMD ["npx", "hardhat", "--config", "./hardhat.config.js", "node"]
\ No newline at end of file
diff --git a/tests/Dockerfile b/tests/Dockerfile_unittest
similarity index 90%
rename from tests/Dockerfile
rename to tests/Dockerfile_unittest
index 391aa407..224711ae 100644
--- a/tests/Dockerfile
+++ b/tests/Dockerfile_unittest
@@ -52,15 +52,16 @@ RUN echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~apl/.bash_profile \
# install python
USER apl
RUN . ~/.bash_profile \
- && pyenv install 3.11.2 \
- && pyenv global 3.11.2 \
+ && pyenv install 3.12.2 \
+ && pyenv global 3.12.2 \
&& pip install --upgrade pip setuptools
# install poetry
RUN . ~/.bash_profile \
- && python -m pip install poetry==1.7.1
+ && python -m pip install poetry==1.8.2
RUN . ~/.bash_profile \
- && poetry config virtualenvs.create false
+ && poetry config virtualenvs.create false \
+ && poetry config installer.max-workers 1
# install python packages
USER root
@@ -88,7 +89,7 @@ COPY pyproject.toml /app/ibet-Prime/pyproject.toml
COPY poetry.lock /app/ibet-Prime/poetry.lock
RUN . ~/.bash_profile \
&& cd /app/ibet-Prime \
- && poetry install --no-root -E ibet-explorer \
+ && poetry install --no-root --all-extras \
&& rm -f /app/ibet-Prime/pyproject.toml \
&& rm -f /app/ibet-Prime/poetry.lock
@@ -97,7 +98,7 @@ USER root
RUN mkdir -p /app/ibet-Prime/tests/
COPY --chown=apl:apl tests/ /app/ibet-Prime/tests/
RUN chmod -R 755 /app/ibet-Prime/tests/
-ENV PYTHONPATH /app/ibet-Prime
+ENV PYTHONPATH /app/ibet-Prime:/app/ibet-Prime/cmd
USER apl
RUN mkdir -p /app/ibet-Prime/cov/
diff --git a/tests/account_config.py b/tests/account_config.py
index 67f6d60b..12e84fcb 100644
--- a/tests/account_config.py
+++ b/tests/account_config.py
@@ -21,12 +21,12 @@
import yaml
from web3 import Web3
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
import config
web3 = Web3(Web3.HTTPProvider(config.WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
# Account Address(from local config)
diff --git a/tests/model/blockchain/test_E2EMessaging.py b/tests/app/model/blockchain/test_E2EMessaging.py
similarity index 99%
rename from tests/model/blockchain/test_E2EMessaging.py
rename to tests/app/model/blockchain/test_E2EMessaging.py
index 9ad1b1fc..7ef20aaa 100644
--- a/tests/model/blockchain/test_E2EMessaging.py
+++ b/tests/app/model/blockchain/test_E2EMessaging.py
@@ -30,7 +30,7 @@
from eth_keyfile import decode_keyfile_json
from web3 import Web3
from web3.exceptions import TimeExhausted
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
from app.exceptions import SendTransactionError
from app.model.blockchain import E2EMessaging
@@ -39,7 +39,7 @@
from tests.account_config import config_eth_account
web3 = Web3(Web3.HTTPProvider(WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
class TestSendMessage:
diff --git a/tests/model/blockchain/test_FreezeLog.py b/tests/app/model/blockchain/test_FreezeLog.py
similarity index 98%
rename from tests/model/blockchain/test_FreezeLog.py
rename to tests/app/model/blockchain/test_FreezeLog.py
index 5dcbf8a6..9fddb383 100644
--- a/tests/model/blockchain/test_FreezeLog.py
+++ b/tests/app/model/blockchain/test_FreezeLog.py
@@ -23,7 +23,7 @@
import pytest
from web3 import Web3
from web3.exceptions import TimeExhausted
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
from app.exceptions import SendTransactionError
from app.model.blockchain import FreezeLogContract
@@ -34,7 +34,7 @@
from tests.account_config import config_eth_account
web3 = Web3(Web3.HTTPProvider(WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
class TestRecordLog:
diff --git a/tests/model/blockchain/test_PersonalInfo.py b/tests/app/model/blockchain/test_PersonalInfo.py
similarity index 98%
rename from tests/model/blockchain/test_PersonalInfo.py
rename to tests/app/model/blockchain/test_PersonalInfo.py
index 1ad69893..a84c98af 100644
--- a/tests/model/blockchain/test_PersonalInfo.py
+++ b/tests/app/model/blockchain/test_PersonalInfo.py
@@ -28,7 +28,7 @@
from eth_keyfile import decode_keyfile_json
from web3 import Web3
from web3.exceptions import ContractLogicError, TimeExhausted
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
from app.exceptions import ContractRevertError, SendTransactionError
from app.model.blockchain import PersonalInfoContract
@@ -39,7 +39,7 @@
from tests.account_config import config_eth_account
web3 = Web3(Web3.HTTPProvider(WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
def initialize(issuer, db):
@@ -161,8 +161,8 @@ async def test_normal_2(self, db):
"address": "test",
"email": "test",
"birth": "test",
- "is_corporate": "test",
- "tax_category": "test",
+ "is_corporate": None,
+ "tax_category": None,
}
###########################################################################
@@ -230,8 +230,8 @@ async def test_error_1(self, db):
"address": "test",
"email": "test",
"birth": "test",
- "is_corporate": "test",
- "tax_category": "test",
+ "is_corporate": None,
+ "tax_category": None,
}
#
@@ -274,8 +274,8 @@ async def test_error_2(self, db):
"address": "test",
"email": "test",
"birth": "test",
- "is_corporate": "test",
- "tax_category": "test",
+ "is_corporate": None,
+ "tax_category": None,
}
diff --git a/tests/model/blockchain/test_TokenList.py b/tests/app/model/blockchain/test_TokenList.py
similarity index 98%
rename from tests/model/blockchain/test_TokenList.py
rename to tests/app/model/blockchain/test_TokenList.py
index b29fb88c..88687b28 100755
--- a/tests/model/blockchain/test_TokenList.py
+++ b/tests/app/model/blockchain/test_TokenList.py
@@ -25,7 +25,7 @@
from eth_keyfile import decode_keyfile_json
from web3 import Web3
from web3.exceptions import ContractLogicError, InvalidAddress, ValidationError
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
import config
from app.exceptions import ContractRevertError, SendTransactionError
@@ -37,7 +37,7 @@
from tests.account_config import config_eth_account
web3 = Web3(Web3.HTTPProvider(WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
@pytest.fixture
diff --git a/tests/model/blockchain/test_exchange_IbetExchangeInterface.py b/tests/app/model/blockchain/test_exchange_IbetExchangeInterface.py
similarity index 98%
rename from tests/model/blockchain/test_exchange_IbetExchangeInterface.py
rename to tests/app/model/blockchain/test_exchange_IbetExchangeInterface.py
index a556db06..a66ac9ad 100644
--- a/tests/model/blockchain/test_exchange_IbetExchangeInterface.py
+++ b/tests/app/model/blockchain/test_exchange_IbetExchangeInterface.py
@@ -20,7 +20,7 @@
import pytest
from eth_keyfile import decode_keyfile_json
from web3 import Web3
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
from app.model.blockchain import IbetExchangeInterface, IbetStraightBondContract
from app.utils.contract_utils import ContractUtils
@@ -28,7 +28,7 @@
from tests.account_config import config_eth_account
web3 = Web3(Web3.HTTPProvider(WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
def deploy_escrow_contract():
diff --git a/tests/model/blockchain/test_exchange_IbetSecurityTokenEscrow.py b/tests/app/model/blockchain/test_exchange_IbetSecurityTokenEscrow.py
similarity index 99%
rename from tests/model/blockchain/test_exchange_IbetSecurityTokenEscrow.py
rename to tests/app/model/blockchain/test_exchange_IbetSecurityTokenEscrow.py
index 9fb05574..4e5a6a72 100644
--- a/tests/model/blockchain/test_exchange_IbetSecurityTokenEscrow.py
+++ b/tests/app/model/blockchain/test_exchange_IbetSecurityTokenEscrow.py
@@ -24,7 +24,7 @@
from eth_keyfile import decode_keyfile_json
from web3 import Web3
from web3.exceptions import ContractLogicError, TimeExhausted
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
from app.exceptions import ContractRevertError, SendTransactionError
from app.model.blockchain import IbetSecurityTokenEscrow, IbetStraightBondContract
@@ -36,7 +36,7 @@
from tests.account_config import config_eth_account
web3 = Web3(Web3.HTTPProvider(WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
def deploy_security_token_escrow_contract():
diff --git a/tests/model/blockchain/test_token_IbetShare.py b/tests/app/model/blockchain/test_token_IbetShare.py
similarity index 98%
rename from tests/model/blockchain/test_token_IbetShare.py
rename to tests/app/model/blockchain/test_token_IbetShare.py
index 173d79de..66261937 100644
--- a/tests/model/blockchain/test_token_IbetShare.py
+++ b/tests/app/model/blockchain/test_token_IbetShare.py
@@ -19,7 +19,7 @@
import time
from binascii import Error
-from datetime import datetime, timedelta
+from datetime import UTC, datetime, timedelta
from unittest import mock
from unittest.mock import ANY, AsyncMock, patch
@@ -52,7 +52,7 @@
from app.utils.contract_utils import ContractUtils
from config import TOKEN_CACHE_TTL, ZERO_ADDRESS
from tests.account_config import config_eth_account
-from tests.utils.contract_utils import (
+from tests.contract_utils import (
IbetSecurityTokenContractTestUtils,
PersonalInfoContractTestUtils,
)
@@ -317,6 +317,7 @@ async def test_normal_1(self, db):
assert share_contract.tradable_exchange_contract_address == ZERO_ADDRESS
assert share_contract.status is True
assert share_contract.personal_info_contract_address == ZERO_ADDRESS
+ assert share_contract.require_personal_info_registered is True
assert share_contract.transferable is False
assert share_contract.is_offering is False
assert share_contract.transfer_approval_required is False
@@ -371,6 +372,7 @@ async def test_normal_2(self, db):
"tradable_exchange_contract_address": "0x1234567890123456789012345678901234567890",
"status": False,
"personal_info_contract_address": "0x1234567890123456789012345678901234567891",
+ "require_personal_info_registered": True,
"transferable": True,
"is_offering": True,
"transfer_approval_required": True,
@@ -386,10 +388,10 @@ async def test_normal_2(self, db):
token_cache = TokenCache()
token_cache.token_address = contract_address
token_cache.attributes = token_attr
- token_cache.cached_datetime = datetime.utcnow()
- token_cache.expiration_datetime = datetime.utcnow() + timedelta(
- seconds=TOKEN_CACHE_TTL
- )
+ token_cache.cached_datetime = datetime.now(UTC).replace(tzinfo=None)
+ token_cache.expiration_datetime = datetime.now(UTC).replace(
+ tzinfo=None
+ ) + timedelta(seconds=TOKEN_CACHE_TTL)
db.add(token_cache)
db.commit()
@@ -413,6 +415,7 @@ async def test_normal_2(self, db):
share_contract.personal_info_contract_address
== "0x1234567890123456789012345678901234567891"
)
+ assert share_contract.require_personal_info_registered is True
assert share_contract.transferable is True
assert share_contract.is_offering is True
assert share_contract.transfer_approval_required is True
@@ -467,6 +470,7 @@ async def test_normal_3(self, db):
"tradable_exchange_contract_address": "0x1234567890123456789012345678901234567890",
"status": False,
"personal_info_contract_address": "0x1234567890123456789012345678901234567891",
+ "require_personal_info_registered": False,
"transferable": True,
"is_offering": True,
"transfer_approval_required": True,
@@ -482,17 +486,17 @@ async def test_normal_3(self, db):
token_cache = TokenCache()
token_cache.token_address = contract_address
token_cache.attributes = token_attr
- token_cache.cached_datetime = datetime.utcnow()
- token_cache.expiration_datetime = datetime.utcnow() + timedelta(
- seconds=TOKEN_CACHE_TTL
- )
+ token_cache.cached_datetime = datetime.now(UTC).replace(tzinfo=None)
+ token_cache.expiration_datetime = datetime.now(UTC).replace(
+ tzinfo=None
+ ) + timedelta(seconds=TOKEN_CACHE_TTL)
db.add(token_cache)
db.commit()
# updated token attribute
_token_attr_update = TokenAttrUpdate()
_token_attr_update.token_address = contract_address
- _token_attr_update.updated_datetime = datetime.utcnow()
+ _token_attr_update.updated_datetime = datetime.now(UTC).replace(tzinfo=None)
db.add(_token_attr_update)
db.commit()
@@ -510,6 +514,7 @@ async def test_normal_3(self, db):
assert share_contract.tradable_exchange_contract_address == ZERO_ADDRESS
assert share_contract.status is True
assert share_contract.personal_info_contract_address == ZERO_ADDRESS
+ assert share_contract.require_personal_info_registered is True
assert share_contract.transferable is False
assert share_contract.is_offering is False
assert share_contract.transfer_approval_required is False
@@ -541,6 +546,7 @@ async def test_normal_4(self, db):
assert share_contract.tradable_exchange_contract_address == ZERO_ADDRESS
assert share_contract.status is True
assert share_contract.personal_info_contract_address == ZERO_ADDRESS
+ assert share_contract.require_personal_info_registered is True
assert share_contract.transferable is False
assert share_contract.is_offering is False
assert share_contract.transfer_approval_required is False
@@ -594,7 +600,7 @@ async def test_normal_1(self, db):
# update
_data = {}
_add_data = UpdateParams(**_data)
- pre_datetime = datetime.utcnow()
+ pre_datetime = datetime.now(UTC).replace(tzinfo=None)
await share_contract.update(
data=_add_data, tx_from=issuer_address, private_key=private_key
)
@@ -607,6 +613,7 @@ async def test_normal_1(self, db):
assert share_contract.dividends == 0.0000000000001
assert share_contract.tradable_exchange_contract_address == ZERO_ADDRESS
assert share_contract.personal_info_contract_address == ZERO_ADDRESS
+ assert share_contract.require_personal_info_registered is True
assert share_contract.transferable is False
assert share_contract.status is True
assert share_contract.is_offering is False
@@ -658,6 +665,7 @@ async def test_normal_2(self, db):
"dividends": 0.01,
"tradable_exchange_contract_address": "0x0000000000000000000000000000000000000001",
"personal_info_contract_address": "0x0000000000000000000000000000000000000002",
+ "require_personal_info_registered": False,
"transferable": False,
"status": False,
"is_offering": True,
@@ -669,7 +677,7 @@ async def test_normal_2(self, db):
"memo": "memo_test",
}
_add_data = UpdateParams(**_data)
- pre_datetime = datetime.utcnow()
+ pre_datetime = datetime.now(UTC).replace(tzinfo=None)
await share_contract.update(
data=_add_data, tx_from=issuer_address, private_key=private_key
)
@@ -688,6 +696,7 @@ async def test_normal_2(self, db):
share_contract.personal_info_contract_address
== "0x0000000000000000000000000000000000000002"
)
+ assert share_contract.require_personal_info_registered is False
assert share_contract.transferable is False
assert share_contract.status is False
assert share_contract.is_offering is True
@@ -901,7 +910,7 @@ async def test_error_5(self, db):
# mock
Web3_send_raw_transaction = patch(
target="web3.eth.async_eth.AsyncEth.wait_for_transaction_receipt",
- side_effect=TransactionNotFound,
+ side_effect=TransactionNotFound(message=""),
)
# update
@@ -1259,7 +1268,7 @@ async def test_error_6(self, db):
# mock
Web3_send_raw_transaction = patch(
target="web3.eth.async_eth.AsyncEth.wait_for_transaction_receipt",
- side_effect=TransactionNotFound,
+ side_effect=TransactionNotFound(message=""),
)
# transfer
@@ -1725,7 +1734,7 @@ async def test_error_5_3(self, db):
# mock
Web3_send_raw_transaction = patch(
target="web3.eth.async_eth.AsyncEth.wait_for_transaction_receipt",
- side_effect=TransactionNotFound,
+ side_effect=TransactionNotFound(message=""),
)
# bulk transfer
@@ -1776,7 +1785,7 @@ async def test_normal_1(self, db):
# additional issue
_data = {"account_address": issuer_address, "amount": 10}
_add_data = AdditionalIssueParams(**_data)
- pre_datetime = datetime.utcnow()
+ pre_datetime = datetime.now(UTC).replace(tzinfo=None)
await share_contract.additional_issue(
data=_add_data, tx_from=issuer_address, private_key=private_key
)
@@ -2004,7 +2013,7 @@ async def test_error_6(self, db):
# mock
Web3_send_raw_transaction = patch(
target="web3.eth.async_eth.AsyncEth.wait_for_transaction_receipt",
- side_effect=TransactionNotFound,
+ side_effect=TransactionNotFound(message=""),
)
# additional issue
@@ -2054,7 +2063,7 @@ async def test_error_7(self, db):
# additional issue
_data = {"account_address": issuer_address, "amount": 10}
_add_data = AdditionalIssueParams(**_data)
- pre_datetime = datetime.utcnow()
+ pre_datetime = datetime.now(UTC).replace(tzinfo=None)
# mock
# NOTE: Ganacheがrevertする際にweb3.pyからraiseされるExceptionはGethと異なる
@@ -2109,7 +2118,7 @@ async def test_normal_1(self, db):
# redeem
_data = {"account_address": issuer_address, "amount": 10}
_add_data = RedeemParams(**_data)
- pre_datetime = datetime.utcnow()
+ pre_datetime = datetime.now(UTC).replace(tzinfo=None)
await share_contract.redeem(
data=_add_data, tx_from=issuer_address, private_key=private_key
)
@@ -2337,7 +2346,7 @@ async def test_error_6(self, db):
# mock
Web3_send_raw_transaction = patch(
target="web3.eth.async_eth.AsyncEth.wait_for_transaction_receipt",
- side_effect=TransactionNotFound,
+ side_effect=TransactionNotFound(message=""),
)
# redeem
@@ -2381,7 +2390,7 @@ async def test_error_7(self, db):
# redeem
_data = {"account_address": issuer_address, "amount": 100_000_000}
_add_data = RedeemParams(**_data)
- pre_datetime = datetime.utcnow()
+ pre_datetime = datetime.now(UTC).replace(tzinfo=None)
# mock
# NOTE: Ganacheがrevertする際にweb3.pyからraiseされるExceptionはGethと異なる
@@ -2502,7 +2511,7 @@ class TestCheckAttrUpdate:
# not exists
@pytest.mark.asyncio
async def test_normal_1(self, async_db):
- before_datetime = datetime.utcnow()
+ before_datetime = datetime.now(UTC).replace(tzinfo=None)
# Test
share_contract = IbetShareContract(self.token_address)
@@ -2515,9 +2524,9 @@ async def test_normal_1(self, async_db):
# prev data exists
@pytest.mark.asyncio
async def test_normal_2(self, async_db):
- before_datetime = datetime.utcnow()
+ before_datetime = datetime.now(UTC).replace(tzinfo=None)
time.sleep(1)
- after_datetime = datetime.utcnow()
+ after_datetime = datetime.now(UTC).replace(tzinfo=None)
# prepare data
_update = TokenAttrUpdate()
@@ -2537,9 +2546,9 @@ async def test_normal_2(self, async_db):
# next data exists
@pytest.mark.asyncio
async def test_normal_3(self, async_db):
- before_datetime = datetime.utcnow()
+ before_datetime = datetime.now(UTC).replace(tzinfo=None)
time.sleep(1)
- after_datetime = datetime.utcnow()
+ after_datetime = datetime.now(UTC).replace(tzinfo=None)
# prepare data
_update = TokenAttrUpdate()
@@ -2589,7 +2598,7 @@ async def test_normal_2(self, async_db, freezer):
# prepare data
_update = TokenAttrUpdate()
_update.token_address = self.token_address
- _update.updated_datetime = datetime.utcnow()
+ _update.updated_datetime = datetime.now(UTC).replace(tzinfo=None)
async_db.add(_update)
await async_db.commit()
@@ -3620,7 +3629,7 @@ async def test_error_4(self, db):
# mock
Web3_send_raw_transaction = patch(
target="web3.eth.async_eth.AsyncEth.wait_for_transaction_receipt",
- side_effect=TransactionNotFound,
+ side_effect=TransactionNotFound(message=""),
)
# lock
@@ -4086,7 +4095,7 @@ async def test_error_4(self, db):
# mock
Web3_send_raw_transaction = patch(
target="web3.eth.async_eth.AsyncEth.wait_for_transaction_receipt",
- side_effect=TransactionNotFound,
+ side_effect=TransactionNotFound(message=""),
)
# forceUnlock
diff --git a/tests/model/blockchain/test_token_IbetStraightBond.py b/tests/app/model/blockchain/test_token_IbetStraightBond.py
similarity index 98%
rename from tests/model/blockchain/test_token_IbetStraightBond.py
rename to tests/app/model/blockchain/test_token_IbetStraightBond.py
index ca802de4..cd2006ee 100644
--- a/tests/model/blockchain/test_token_IbetStraightBond.py
+++ b/tests/app/model/blockchain/test_token_IbetStraightBond.py
@@ -19,7 +19,7 @@
import time
from binascii import Error
-from datetime import datetime, timedelta
+from datetime import UTC, datetime, timedelta
from unittest import mock
from unittest.mock import ANY, MagicMock, patch
@@ -52,7 +52,7 @@
from app.utils.contract_utils import ContractUtils
from config import DEFAULT_CURRENCY, TOKEN_CACHE_TTL, ZERO_ADDRESS
from tests.account_config import config_eth_account
-from tests.utils.contract_utils import (
+from tests.contract_utils import (
IbetSecurityTokenContractTestUtils,
PersonalInfoContractTestUtils,
)
@@ -309,7 +309,7 @@ async def test_normal_1(self, db):
)
# get token data
- pre_datetime = datetime.utcnow()
+ pre_datetime = datetime.now(UTC).replace(tzinfo=None)
bond_contract = await IbetStraightBondContract(contract_address).get()
# assertion
@@ -323,6 +323,7 @@ async def test_normal_1(self, db):
assert bond_contract.tradable_exchange_contract_address == ZERO_ADDRESS
assert bond_contract.status is True
assert bond_contract.personal_info_contract_address == ZERO_ADDRESS
+ assert bond_contract.require_personal_info_registered is True
assert bond_contract.transferable is False
assert bond_contract.is_offering is False
assert bond_contract.transfer_approval_required is False
@@ -396,6 +397,7 @@ async def test_normal_2(self, db):
"tradable_exchange_contract_address": "0x1234567890123456789012345678901234567890",
"status": False,
"personal_info_contract_address": "0x1234567890123456789012345678901234567891",
+ "require_personal_info_registered": True,
"transferable": True,
"is_offering": True,
"transfer_approval_required": True,
@@ -430,10 +432,10 @@ async def test_normal_2(self, db):
token_cache = TokenCache()
token_cache.token_address = contract_address
token_cache.attributes = token_attr
- token_cache.cached_datetime = datetime.utcnow()
- token_cache.expiration_datetime = datetime.utcnow() + timedelta(
- seconds=TOKEN_CACHE_TTL
- )
+ token_cache.cached_datetime = datetime.now(UTC).replace(tzinfo=None)
+ token_cache.expiration_datetime = datetime.now(UTC).replace(
+ tzinfo=None
+ ) + timedelta(seconds=TOKEN_CACHE_TTL)
db.add(token_cache)
db.commit()
@@ -457,6 +459,7 @@ async def test_normal_2(self, db):
bond_contract.personal_info_contract_address
== "0x1234567890123456789012345678901234567891"
)
+ assert bond_contract.require_personal_info_registered is True
assert bond_contract.transferable is True
assert bond_contract.is_offering is True
assert bond_contract.transfer_approval_required is True
@@ -530,6 +533,7 @@ async def test_normal_3(self, db):
"tradable_exchange_contract_address": "0x1234567890123456789012345678901234567890",
"status": False,
"personal_info_contract_address": "0x1234567890123456789012345678901234567891",
+ "require_personal_info_registered": False,
"transferable": True,
"is_offering": True,
"transfer_approval_required": True,
@@ -564,16 +568,16 @@ async def test_normal_3(self, db):
token_cache = TokenCache()
token_cache.token_address = contract_address
token_cache.attributes = token_attr
- token_cache.cached_datetime = datetime.utcnow()
- token_cache.expiration_datetime = datetime.utcnow() + timedelta(
- seconds=TOKEN_CACHE_TTL
- )
+ token_cache.cached_datetime = datetime.now(UTC).replace(tzinfo=None)
+ token_cache.expiration_datetime = datetime.now(UTC).replace(
+ tzinfo=None
+ ) + timedelta(seconds=TOKEN_CACHE_TTL)
db.add(token_cache)
# updated token attribute
_token_attr_update = TokenAttrUpdate()
_token_attr_update.token_address = contract_address
- _token_attr_update.updated_datetime = datetime.utcnow()
+ _token_attr_update.updated_datetime = datetime.now(UTC).replace(tzinfo=None)
db.add(_token_attr_update)
db.commit()
@@ -591,6 +595,7 @@ async def test_normal_3(self, db):
assert bond_contract.tradable_exchange_contract_address == ZERO_ADDRESS
assert bond_contract.status is True
assert bond_contract.personal_info_contract_address == ZERO_ADDRESS
+ assert bond_contract.require_personal_info_registered is True
assert bond_contract.transferable is False
assert bond_contract.is_offering is False
assert bond_contract.transfer_approval_required is False
@@ -640,6 +645,7 @@ async def test_normal_4(self, db):
assert bond_contract.tradable_exchange_contract_address == ZERO_ADDRESS
assert bond_contract.status is True
assert bond_contract.personal_info_contract_address == ZERO_ADDRESS
+ assert bond_contract.require_personal_info_registered is True
assert bond_contract.transferable is False
assert bond_contract.is_offering is False
assert bond_contract.transfer_approval_required is False
@@ -714,7 +720,7 @@ async def test_normal_1(self, db):
# update
_data = {}
_add_data = UpdateParams(**_data)
- pre_datetime = datetime.utcnow()
+ pre_datetime = datetime.now(UTC).replace(tzinfo=None)
await bond_contract.update(
data=_add_data, tx_from=issuer_address, private_key=private_key
)
@@ -752,6 +758,7 @@ async def test_normal_1(self, db):
assert bond_contract.is_redeemed is False
assert bond_contract.tradable_exchange_contract_address == ZERO_ADDRESS
assert bond_contract.personal_info_contract_address == ZERO_ADDRESS
+ assert bond_contract.require_personal_info_registered is True
assert bond_contract.contact_information == ""
assert bond_contract.privacy_policy == ""
assert bond_contract.transfer_approval_required is False
@@ -808,13 +815,14 @@ async def test_normal_2(self, db):
"is_redeemed": True,
"tradable_exchange_contract_address": "0x0000000000000000000000000000000000000001",
"personal_info_contract_address": "0x0000000000000000000000000000000000000002",
+ "require_personal_info_registered": False,
"contact_information": "contact info test",
"privacy_policy": "privacy policy test",
"transfer_approval_required": True,
"memo": "memo test",
}
_add_data = UpdateParams(**_data)
- pre_datetime = datetime.utcnow()
+ pre_datetime = datetime.now(UTC).replace(tzinfo=None)
await bond_contract.update(
data=_add_data, tx_from=issuer_address, private_key=private_key
)
@@ -854,6 +862,7 @@ async def test_normal_2(self, db):
bond_contract.personal_info_contract_address
== "0x0000000000000000000000000000000000000002"
)
+ assert bond_contract.require_personal_info_registered is False
assert bond_contract.contact_information == "contact info test"
assert bond_contract.privacy_policy == "privacy policy test"
assert bond_contract.transfer_approval_required is True
@@ -1116,7 +1125,7 @@ async def test_error_5(self, db):
# mock
Web3_send_raw_transaction = patch(
target="web3.eth.async_eth.AsyncEth.wait_for_transaction_receipt",
- side_effect=TransactionNotFound,
+ side_effect=TransactionNotFound(message=""),
)
# update
@@ -1488,7 +1497,7 @@ async def test_error_6(self, db):
# mock
Web3_send_raw_transaction = patch(
target="web3.eth.async_eth.AsyncEth.wait_for_transaction_receipt",
- side_effect=TransactionNotFound,
+ side_effect=TransactionNotFound(message=""),
)
# transfer
@@ -1968,7 +1977,7 @@ async def test_error_5_3(self, db):
# mock
Web3_send_raw_transaction = patch(
target="web3.eth.async_eth.AsyncEth.wait_for_transaction_receipt",
- side_effect=TransactionNotFound,
+ side_effect=TransactionNotFound(message=""),
)
# bulk transfer
@@ -2021,7 +2030,7 @@ async def test_normal_1(self, db):
# additional issue
_data = {"account_address": issuer_address, "amount": 10}
_add_data = AdditionalIssueParams(**_data)
- pre_datetime = datetime.utcnow()
+ pre_datetime = datetime.now(UTC).replace(tzinfo=None)
await bond_contract.additional_issue(
data=_add_data, tx_from=issuer_address, private_key=private_key
)
@@ -2257,7 +2266,7 @@ async def test_error_6(self, db):
# mock
Web3_send_raw_transaction = patch(
target="web3.eth.async_eth.AsyncEth.wait_for_transaction_receipt",
- side_effect=TransactionNotFound,
+ side_effect=TransactionNotFound(message=""),
)
# additional issue
@@ -2309,7 +2318,7 @@ async def test_error_7(self, db):
# additional issue
_data = {"account_address": issuer_address, "amount": 10}
_add_data = AdditionalIssueParams(**_data)
- pre_datetime = datetime.utcnow()
+ pre_datetime = datetime.now(UTC).replace(tzinfo=None)
# mock
# NOTE: Ganacheがrevertする際にweb3.pyからraiseされるExceptionはGethと異なる
@@ -2366,7 +2375,7 @@ async def test_normal_1(self, db):
# redeem
_data = {"account_address": issuer_address, "amount": 10}
_add_data = RedeemParams(**_data)
- pre_datetime = datetime.utcnow()
+ pre_datetime = datetime.now(UTC).replace(tzinfo=None)
await bond_contract.redeem(
data=_add_data, tx_from=issuer_address, private_key=private_key
)
@@ -2602,7 +2611,7 @@ async def test_error_6(self, db):
# mock
Web3_send_raw_transaction = patch(
target="web3.eth.async_eth.AsyncEth.wait_for_transaction_receipt",
- side_effect=TransactionNotFound,
+ side_effect=TransactionNotFound(message=""),
)
# redeem
@@ -2648,7 +2657,7 @@ async def test_error_7(self, db):
# redeem
_data = {"account_address": issuer_address, "amount": 100_000_000}
_add_data = RedeemParams(**_data)
- pre_datetime = datetime.utcnow()
+ pre_datetime = datetime.now(UTC).replace(tzinfo=None)
# mock
# NOTE: Ganacheがrevertする際にweb3.pyからraiseされるExceptionはGethと異なる
@@ -2773,7 +2782,7 @@ class TestCheckAttrUpdate:
# not exists
@pytest.mark.asyncio
async def test_normal_1(self, async_db):
- before_datetime = datetime.utcnow()
+ before_datetime = datetime.now(UTC).replace(tzinfo=None)
# Test
bond_contract = IbetStraightBondContract(self.token_address)
@@ -2786,9 +2795,9 @@ async def test_normal_1(self, async_db):
# prev data exists
@pytest.mark.asyncio
async def test_normal_2(self, async_db):
- before_datetime = datetime.utcnow()
+ before_datetime = datetime.now(UTC).replace(tzinfo=None)
time.sleep(1)
- after_datetime = datetime.utcnow()
+ after_datetime = datetime.now(UTC).replace(tzinfo=None)
# prepare data
_update = TokenAttrUpdate()
@@ -2808,9 +2817,9 @@ async def test_normal_2(self, async_db):
# next data exists
@pytest.mark.asyncio
async def test_normal_3(self, async_db):
- before_datetime = datetime.utcnow()
+ before_datetime = datetime.now(UTC).replace(tzinfo=None)
time.sleep(1)
- after_datetime = datetime.utcnow()
+ after_datetime = datetime.now(UTC).replace(tzinfo=None)
# prepare data
_update = TokenAttrUpdate()
@@ -2860,7 +2869,7 @@ async def test_normal_2(self, async_db, freezer):
# prepare data
_update = TokenAttrUpdate()
_update.token_address = self.token_address
- _update.updated_datetime = datetime.utcnow()
+ _update.updated_datetime = datetime.now(UTC).replace(tzinfo=None)
async_db.add(_update)
await async_db.commit()
@@ -3915,7 +3924,7 @@ async def test_error_4(self, db):
# mock
Web3_send_raw_transaction = patch(
target="web3.eth.async_eth.AsyncEth.wait_for_transaction_receipt",
- side_effect=TransactionNotFound,
+ side_effect=TransactionNotFound(message=""),
)
# lock
@@ -4393,7 +4402,7 @@ async def test_error_4(self, db):
# mock
Web3_send_raw_transaction = patch(
target="web3.eth.async_eth.AsyncEth.wait_for_transaction_receipt",
- side_effect=TransactionNotFound,
+ side_effect=TransactionNotFound(message=""),
)
# forceUnlock
diff --git a/tests/test_app_routers_accounts_GET.py b/tests/app/test_accounts_GET.py
similarity index 100%
rename from tests/test_app_routers_accounts_GET.py
rename to tests/app/test_accounts_GET.py
diff --git a/tests/test_app_routers_accounts_POST.py b/tests/app/test_accounts_POST.py
similarity index 100%
rename from tests/test_app_routers_accounts_POST.py
rename to tests/app/test_accounts_POST.py
diff --git a/tests/test_app_routers_accounts_{issuer_address}_DELETE.py b/tests/app/test_accounts_{issuer_address}_DELETE.py
similarity index 100%
rename from tests/test_app_routers_accounts_{issuer_address}_DELETE.py
rename to tests/app/test_accounts_{issuer_address}_DELETE.py
diff --git a/tests/test_app_routers_accounts_{issuer_address}_GET.py b/tests/app/test_accounts_{issuer_address}_GET.py
similarity index 100%
rename from tests/test_app_routers_accounts_{issuer_address}_GET.py
rename to tests/app/test_accounts_{issuer_address}_GET.py
diff --git a/tests/test_app_routers_accounts_{issuer_address}_authtoken_DELETE.py b/tests/app/test_accounts_{issuer_address}_authtoken_DELETE.py
similarity index 100%
rename from tests/test_app_routers_accounts_{issuer_address}_authtoken_DELETE.py
rename to tests/app/test_accounts_{issuer_address}_authtoken_DELETE.py
diff --git a/tests/test_app_routers_accounts_{issuer_address}_authtoken_POST.py b/tests/app/test_accounts_{issuer_address}_authtoken_POST.py
similarity index 100%
rename from tests/test_app_routers_accounts_{issuer_address}_authtoken_POST.py
rename to tests/app/test_accounts_{issuer_address}_authtoken_POST.py
diff --git a/tests/test_app_routers_accounts_{issuer_address}_eoa_password_POST.py b/tests/app/test_accounts_{issuer_address}_eoa_password_POST.py
similarity index 100%
rename from tests/test_app_routers_accounts_{issuer_address}_eoa_password_POST.py
rename to tests/app/test_accounts_{issuer_address}_eoa_password_POST.py
diff --git a/tests/test_app_routers_accounts_{issuer_address}_rsa_passphrase_POST.py b/tests/app/test_accounts_{issuer_address}_rsa_passphrase_POST.py
similarity index 100%
rename from tests/test_app_routers_accounts_{issuer_address}_rsa_passphrase_POST.py
rename to tests/app/test_accounts_{issuer_address}_rsa_passphrase_POST.py
diff --git a/tests/test_app_routers_accounts_{issuer_address}_rsakey_POST.py b/tests/app/test_accounts_{issuer_address}_rsakey_POST.py
similarity index 100%
rename from tests/test_app_routers_accounts_{issuer_address}_rsakey_POST.py
rename to tests/app/test_accounts_{issuer_address}_rsakey_POST.py
diff --git a/tests/test_app_routers_block_number_GET.py b/tests/app/test_block_number_GET.py
similarity index 100%
rename from tests/test_app_routers_block_number_GET.py
rename to tests/app/test_block_number_GET.py
diff --git a/tests/test_app_routers_blockchain_explorer_block_data_GET.py b/tests/app/test_blockchain_explorer_block_data_GET.py
similarity index 100%
rename from tests/test_app_routers_blockchain_explorer_block_data_GET.py
rename to tests/app/test_blockchain_explorer_block_data_GET.py
diff --git a/tests/test_app_routers_blockchain_explorer_block_data_{block_number}_GET.py b/tests/app/test_blockchain_explorer_block_data_{block_number}_GET.py
similarity index 100%
rename from tests/test_app_routers_blockchain_explorer_block_data_{block_number}_GET.py
rename to tests/app/test_blockchain_explorer_block_data_{block_number}_GET.py
diff --git a/tests/test_app_routers_blockchain_explorer_tx_data_GET.py b/tests/app/test_blockchain_explorer_tx_data_GET.py
similarity index 100%
rename from tests/test_app_routers_blockchain_explorer_tx_data_GET.py
rename to tests/app/test_blockchain_explorer_tx_data_GET.py
diff --git a/tests/test_app_routers_blockchain_explorer_tx_data_{hash}_GET.py b/tests/app/test_blockchain_explorer_tx_data_{hash}_GET.py
similarity index 99%
rename from tests/test_app_routers_blockchain_explorer_tx_data_{hash}_GET.py
rename to tests/app/test_blockchain_explorer_tx_data_{hash}_GET.py
index f8d82289..137807fb 100644
--- a/tests/test_app_routers_blockchain_explorer_tx_data_{hash}_GET.py
+++ b/tests/app/test_blockchain_explorer_tx_data_{hash}_GET.py
@@ -70,7 +70,7 @@ def insert_token_data(session, token_info):
token.issuer_address = ""
token.token_address = token_info.get("token_address")
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
session.add(token)
session.commit()
diff --git a/tests/test_app_routers_bond_bulk_transfer_GET.py b/tests/app/test_bond_bulk_transfer_GET.py
similarity index 97%
rename from tests/test_app_routers_bond_bulk_transfer_GET.py
rename to tests/app/test_bond_bulk_transfer_GET.py
index 0292760a..d4617f59 100644
--- a/tests/test_app_routers_bond_bulk_transfer_GET.py
+++ b/tests/app/test_bond_bulk_transfer_GET.py
@@ -17,7 +17,7 @@
SPDX-License-Identifier: Apache-2.0
"""
-from datetime import datetime
+from datetime import UTC, datetime
import pytest
import pytz
@@ -70,7 +70,7 @@ def test_normal_1(self, client, db):
db.add(account)
# prepare data : BulkTransferUpload
- utc_now = datetime.utcnow()
+ utc_now = datetime.now(UTC).replace(tzinfo=None)
for i in range(0, 3):
bulk_transfer_upload = BulkTransferUpload()
bulk_transfer_upload.issuer_address = self.upload_issuer_list[i]["address"]
@@ -110,7 +110,7 @@ def test_normal_1(self, client, db):
@pytest.mark.freeze_time("2021-05-20 12:34:56")
def test_normal_2(self, client, db):
# prepare data : BulkTransferUpload
- utc_now = datetime.utcnow()
+ utc_now = datetime.now(UTC).replace(tzinfo=None)
for i in range(0, 3):
bulk_transfer_upload = BulkTransferUpload()
bulk_transfer_upload.issuer_address = self.upload_issuer_list[i]["address"]
diff --git a/tests/test_app_routers_bond_bulk_transfer_POST.py b/tests/app/test_bond_bulk_transfer_POST.py
similarity index 98%
rename from tests/test_app_routers_bond_bulk_transfer_POST.py
rename to tests/app/test_bond_bulk_transfer_POST.py
index 19f3568d..6e9059f0 100644
--- a/tests/test_app_routers_bond_bulk_transfer_POST.py
+++ b/tests/app/test_bond_bulk_transfer_POST.py
@@ -83,7 +83,7 @@ def test_normal_1(self, client, db):
_token.issuer_address = self.admin_address
_token.token_address = _t
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -172,7 +172,7 @@ def test_normal_2(self, client, db):
_token.issuer_address = self.admin_address
_token.token_address = _t
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -254,7 +254,7 @@ def test_normal_3(self, client, db):
_token.issuer_address = self.from_address
_token.token_address = _t
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -693,7 +693,7 @@ def test_error_10(self, client, db):
_token.token_address = self.req_tokens[0]
_token.abi = ""
_token.token_status = 0
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -743,7 +743,7 @@ def test_error_11_1(self, client, db):
_token.issuer_address = self.from_address
_token.token_address = _t
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -801,7 +801,7 @@ def test_error_11_2(self, client, db):
_token.issuer_address = self.from_address
_token.token_address = _t
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -859,7 +859,7 @@ def test_error_11_3(self, client, db):
_token.issuer_address = self.admin_address
_token.token_address = _t
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
diff --git a/tests/test_app_routers_bond_bulk_transfer_{upload_id}_GET.py b/tests/app/test_bond_bulk_transfer_{upload_id}_GET.py
similarity index 100%
rename from tests/test_app_routers_bond_bulk_transfer_{upload_id}_GET.py
rename to tests/app/test_bond_bulk_transfer_{upload_id}_GET.py
diff --git a/tests/test_app_routers_bond_lock_events_GET.py b/tests/app/test_bond_lock_events_GET.py
similarity index 97%
rename from tests/test_app_routers_bond_lock_events_GET.py
rename to tests/app/test_bond_lock_events_GET.py
index f4425160..4b50e4e4 100644
--- a/tests/test_app_routers_bond_lock_events_GET.py
+++ b/tests/app/test_bond_lock_events_GET.py
@@ -17,7 +17,7 @@
SPDX-License-Identifier: Apache-2.0
"""
-from datetime import datetime
+from datetime import UTC, datetime
from unittest import mock
from unittest.mock import ANY, AsyncMock
@@ -56,7 +56,7 @@ def setup_data(self, db: Session, token_status: int = 1):
_token.tx_hash = ""
_token.abi = ""
_token.token_status = token_status
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Token
@@ -67,7 +67,7 @@ def setup_data(self, db: Session, token_status: int = 1):
_token.tx_hash = ""
_token.abi = ""
_token.token_status = token_status
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Lock events
@@ -80,7 +80,7 @@ def setup_data(self, db: Session, token_status: int = 1):
_lock.account_address = self.account_address_1
_lock.value = 1
_lock.data = {"message": "locked_1"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
_lock = IDXLock()
@@ -92,7 +92,7 @@ def setup_data(self, db: Session, token_status: int = 1):
_lock.account_address = self.account_address_2
_lock.value = 1
_lock.data = {"message": "locked_2"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
_unlock = IDXUnlock()
@@ -105,7 +105,7 @@ def setup_data(self, db: Session, token_status: int = 1):
_unlock.recipient_address = self.other_account_address_1
_unlock.value = 1
_unlock.data = {"message": "unlocked_1"}
- _unlock.block_timestamp = datetime.utcnow()
+ _unlock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_unlock)
_unlock = IDXUnlock()
@@ -118,7 +118,7 @@ def setup_data(self, db: Session, token_status: int = 1):
_unlock.recipient_address = self.other_account_address_2
_unlock.value = 1
_unlock.data = {"message": "unlocked_2"}
- _unlock.block_timestamp = datetime.utcnow()
+ _unlock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_unlock)
db.commit()
@@ -207,7 +207,7 @@ def test_normal_1(self, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
diff --git a/tests/test_app_routers_bond_tokens_GET.py b/tests/app/test_bond_tokens_GET.py
similarity index 95%
rename from tests/test_app_routers_bond_tokens_GET.py
rename to tests/app/test_bond_tokens_GET.py
index 835c13d5..b3f400c2 100644
--- a/tests/test_app_routers_bond_tokens_GET.py
+++ b/tests/app/test_bond_tokens_GET.py
@@ -58,7 +58,7 @@ def test_normal_2(self, mock_get, client, db):
token.issuer_address = issuer_address_1
token.token_address = "token_address_test1"
token.abi = "abi_test1"
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
_issue_datetime = (
@@ -96,6 +96,7 @@ def test_normal_2(self, mock_get, client, db):
mock_token.personal_info_contract_address = (
"0x1234567890aBcDFE1234567890abcDFE12345679"
)
+ mock_token.require_personal_info_registered = True
mock_token.interest_payment_date = [
"interestPaymentDate1_test1",
"interestPaymentDate2_test1",
@@ -156,13 +157,14 @@ def test_normal_2(self, mock_get, client, db):
"is_offering": False,
"tradable_exchange_contract_address": "0x1234567890abCdFe1234567890ABCdFE12345678",
"personal_info_contract_address": "0x1234567890aBcDFE1234567890abcDFE12345679",
+ "require_personal_info_registered": True,
"contact_information": "contactInformation_test1",
"privacy_policy": "privacyPolicy_test1",
"issue_datetime": _issue_datetime,
"token_status": 1,
"transfer_approval_required": True,
"memo": "memo_test1",
- "contract_version": TokenVersion.V_23_12,
+ "contract_version": TokenVersion.V_24_06,
}
]
@@ -185,7 +187,7 @@ def test_normal_3(self, mock_get, client, db):
token_1.issuer_address = issuer_address_1
token_1.token_address = "token_address_test1"
token_1.abi = "abi_test1"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
_issue_datetime_1 = (
@@ -222,6 +224,7 @@ def test_normal_3(self, mock_get, client, db):
mock_token_1.personal_info_contract_address = (
"0x1234567890aBcDFE1234567890abcDFE12345679"
)
+ mock_token_1.require_personal_info_registered = True
mock_token_1.interest_payment_date = [
"interestPaymentDate1_test1",
"interestPaymentDate2_test1",
@@ -249,7 +252,7 @@ def test_normal_3(self, mock_get, client, db):
token_2.token_address = "token_address_test2"
token_2.abi = "abi_test2"
token_2.token_status = 0
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
_issue_datetime_2 = (
@@ -286,6 +289,7 @@ def test_normal_3(self, mock_get, client, db):
mock_token_2.personal_info_contract_address = (
"0x1234567890abcdFE1234567890ABcdfE12345681"
)
+ mock_token_2.require_personal_info_registered = False
mock_token_2.interest_payment_date = [
"interestPaymentDate1_test2",
"interestPaymentDate2_test2",
@@ -350,13 +354,14 @@ def test_normal_3(self, mock_get, client, db):
"is_offering": False,
"tradable_exchange_contract_address": "0x1234567890abCdFe1234567890ABCdFE12345678",
"personal_info_contract_address": "0x1234567890aBcDFE1234567890abcDFE12345679",
+ "require_personal_info_registered": True,
"contact_information": "contactInformation_test1",
"privacy_policy": "privacyPolicy_test1",
"issue_datetime": _issue_datetime_1,
"token_status": 1,
"transfer_approval_required": True,
"memo": "memo_test1",
- "contract_version": TokenVersion.V_23_12,
+ "contract_version": TokenVersion.V_24_06,
},
{
"issuer_address": token_2.issuer_address,
@@ -395,13 +400,14 @@ def test_normal_3(self, mock_get, client, db):
"is_offering": False,
"tradable_exchange_contract_address": "0x1234567890AbcdfE1234567890abcdfE12345680",
"personal_info_contract_address": "0x1234567890abcdFE1234567890ABcdfE12345681",
+ "require_personal_info_registered": False,
"contact_information": "contactInformation_test2",
"privacy_policy": "privacyPolicy_test2",
"issue_datetime": _issue_datetime_2,
"token_status": 0,
"transfer_approval_required": False,
"memo": "memo_test2",
- "contract_version": TokenVersion.V_23_12,
+ "contract_version": TokenVersion.V_24_06,
},
]
@@ -423,7 +429,7 @@ def test_normal_4(self, client, db):
token.issuer_address = issuer_address_1
token.token_address = "token_address_test1"
token.abi = "abi_test1"
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
resp = client.get(self.apiurl, headers={"issuer-address": issuer_address_2})
@@ -446,7 +452,7 @@ def test_normal_5(self, mock_get, client, db):
token_1.issuer_address = issuer_address_1
token_1.token_address = "token_address_test1"
token_1.abi = "abi_test1"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
_issue_datetime = (
@@ -484,6 +490,7 @@ def test_normal_5(self, mock_get, client, db):
mock_token.personal_info_contract_address = (
"0x1234567890aBcDFE1234567890abcDFE12345679"
)
+ mock_token.require_personal_info_registered = True
mock_token.interest_payment_date = [
"interestPaymentDate1_test1",
"interestPaymentDate2_test1",
@@ -511,7 +518,7 @@ def test_normal_5(self, mock_get, client, db):
token_2.issuer_address = issuer_address_2
token_2.token_address = "token_address_test1"
token_2.abi = "abi_test1"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
resp = client.get(self.apiurl, headers={"issuer-address": issuer_address_1})
@@ -554,13 +561,14 @@ def test_normal_5(self, mock_get, client, db):
"is_offering": False,
"tradable_exchange_contract_address": "0x1234567890abCdFe1234567890ABCdFE12345678",
"personal_info_contract_address": "0x1234567890aBcDFE1234567890abcDFE12345679",
+ "require_personal_info_registered": True,
"contact_information": "contactInformation_test1",
"privacy_policy": "privacyPolicy_test1",
"issue_datetime": _issue_datetime,
"token_status": 1,
"transfer_approval_required": True,
"memo": "memo_test1",
- "contract_version": TokenVersion.V_23_12,
+ "contract_version": TokenVersion.V_24_06,
}
]
@@ -583,7 +591,7 @@ def test_normal_6(self, mock_get, client, db):
token_1.issuer_address = issuer_address_1
token_1.token_address = "token_address_test1"
token_1.abi = "abi_test1"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
_issue_datetime_1 = (
@@ -620,6 +628,7 @@ def test_normal_6(self, mock_get, client, db):
mock_token_1.personal_info_contract_address = (
"0x1234567890aBcDFE1234567890abcDFE12345679"
)
+ mock_token_1.require_personal_info_registered = True
mock_token_1.interest_payment_date = [
"interestPaymentDate1_test1",
"interestPaymentDate2_test1",
@@ -647,7 +656,7 @@ def test_normal_6(self, mock_get, client, db):
token_2.token_address = "token_address_test2"
token_2.abi = "abi_test2"
token_2.token_status = 0
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
_issue_datetime_2 = (
@@ -684,6 +693,7 @@ def test_normal_6(self, mock_get, client, db):
mock_token_2.personal_info_contract_address = (
"0x1234567890abcdFE1234567890ABcdfE12345681"
)
+ mock_token_2.require_personal_info_registered = True
mock_token_2.interest_payment_date = [
"interestPaymentDate1_test2",
"interestPaymentDate2_test2",
@@ -715,7 +725,7 @@ def test_normal_6(self, mock_get, client, db):
token_3.issuer_address = issuer_address_2
token_3.token_address = "token_address_test1"
token_3.abi = "abi_test1"
- token_3.version = TokenVersion.V_23_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
resp = client.get(self.apiurl, headers={"issuer-address": issuer_address_1})
@@ -758,13 +768,14 @@ def test_normal_6(self, mock_get, client, db):
"is_offering": False,
"tradable_exchange_contract_address": "0x1234567890abCdFe1234567890ABCdFE12345678",
"personal_info_contract_address": "0x1234567890aBcDFE1234567890abcDFE12345679",
+ "require_personal_info_registered": True,
"contact_information": "contactInformation_test1",
"privacy_policy": "privacyPolicy_test1",
"issue_datetime": _issue_datetime_1,
"token_status": 1,
"transfer_approval_required": True,
"memo": "memo_test1",
- "contract_version": TokenVersion.V_23_12,
+ "contract_version": TokenVersion.V_24_06,
},
{
"issuer_address": token_2.issuer_address,
@@ -803,13 +814,14 @@ def test_normal_6(self, mock_get, client, db):
"is_offering": False,
"tradable_exchange_contract_address": "0x1234567890AbcdfE1234567890abcdfE12345680",
"personal_info_contract_address": "0x1234567890abcdFE1234567890ABcdfE12345681",
+ "require_personal_info_registered": True,
"contact_information": "contactInformation_test2",
"privacy_policy": "privacyPolicy_test2",
"issue_datetime": _issue_datetime_2,
"token_status": 0,
"transfer_approval_required": False,
"memo": "memo_test2",
- "contract_version": TokenVersion.V_23_12,
+ "contract_version": TokenVersion.V_24_06,
},
]
diff --git a/tests/test_app_routers_bond_tokens_POST.py b/tests/app/test_bond_tokens_POST.py
similarity index 98%
rename from tests/test_app_routers_bond_tokens_POST.py
rename to tests/app/test_bond_tokens_POST.py
index adf569b5..af6f7df9 100644
--- a/tests/test_app_routers_bond_tokens_POST.py
+++ b/tests/app/test_bond_tokens_POST.py
@@ -20,13 +20,13 @@
import hashlib
import random
import string
-from datetime import datetime, timezone
+from datetime import UTC, datetime
from unittest.mock import ANY, patch
import pytest
from sqlalchemy import select
from web3 import Web3
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
import config
from app.exceptions import SendTransactionError
@@ -48,7 +48,7 @@
from tests.account_config import config_eth_account
web3 = Web3(Web3.HTTPProvider(config.WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
class TestAppRoutersBondTokensPOST:
@@ -93,9 +93,7 @@ async def test_normal_1(self, client, db):
target="app.utils.contract_utils.AsyncContractUtils.get_block_by_transaction_hash",
return_value={
"number": 12345,
- "timestamp": datetime(
- 2021, 4, 27, 12, 34, 56, tzinfo=timezone.utc
- ).timestamp(),
+ "timestamp": datetime(2021, 4, 27, 12, 34, 56, tzinfo=UTC).timestamp(),
},
)
@@ -168,7 +166,7 @@ async def test_normal_1(self, client, db):
assert token_1.token_address == "contract_address_test1"
assert token_1.abi == "abi_test1"
assert token_1.token_status == 1
- assert token_1.version == TokenVersion.V_23_12
+ assert token_1.version == TokenVersion.V_24_06
position = db.scalars(select(IDXPosition).limit(1)).first()
assert position.token_address == "contract_address_test1"
@@ -224,9 +222,7 @@ async def test_normal_2(self, client, db):
target="app.utils.contract_utils.AsyncContractUtils.get_block_by_transaction_hash",
return_value={
"number": 12345,
- "timestamp": datetime(
- 2021, 4, 27, 12, 34, 56, tzinfo=timezone.utc
- ).timestamp(),
+ "timestamp": datetime(2021, 4, 27, 12, 34, 56, tzinfo=UTC).timestamp(),
},
)
@@ -257,6 +253,7 @@ async def test_normal_2(self, client, db):
"is_redeemed": True, # update
"tradable_exchange_contract_address": "0x0000000000000000000000000000000000000001", # update
"personal_info_contract_address": "0x0000000000000000000000000000000000000002", # update
+ "require_personal_info_registered": False, # update
"contact_information": "contact info test", # update
"privacy_policy": "privacy policy test", # update
"transfer_approval_required": True, # update
@@ -310,7 +307,7 @@ async def test_normal_2(self, client, db):
assert token_1.token_address == "contract_address_test1"
assert token_1.abi == "abi_test1"
assert token_1.token_status == 0
- assert token_1.version == TokenVersion.V_23_12
+ assert token_1.version == TokenVersion.V_24_06
position = db.scalars(select(IDXPosition).limit(1)).first()
assert position is None
@@ -367,9 +364,7 @@ async def test_normal_3(self, client, db):
target="app.utils.contract_utils.AsyncContractUtils.get_block_by_transaction_hash",
return_value={
"number": 12345,
- "timestamp": datetime(
- 2021, 4, 27, 12, 34, 56, tzinfo=timezone.utc
- ).timestamp(),
+ "timestamp": datetime(2021, 4, 27, 12, 34, 56, tzinfo=UTC).timestamp(),
},
)
@@ -442,7 +437,7 @@ async def test_normal_3(self, client, db):
assert token_1.token_address == "contract_address_test1"
assert token_1.abi == "abi_test1"
assert token_1.token_status == 1
- assert token_1.version == TokenVersion.V_23_12
+ assert token_1.version == TokenVersion.V_24_06
position = db.scalars(select(IDXPosition).limit(1)).first()
assert position.token_address == "contract_address_test1"
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_GET.py b/tests/app/test_bond_tokens_{token_address}_GET.py
similarity index 96%
rename from tests/test_app_routers_bond_tokens_{token_address}_GET.py
rename to tests/app/test_bond_tokens_{token_address}_GET.py
index 18a8b21f..77e0a7b2 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_GET.py
+++ b/tests/app/test_bond_tokens_{token_address}_GET.py
@@ -46,7 +46,7 @@ def test_normal_1(self, mock_get, client, db):
token.issuer_address = "issuer_address_test1"
token.token_address = "token_address_test1"
token.abi = "abi_test1"
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -87,6 +87,7 @@ def test_normal_1(self, mock_get, client, db):
mock_token.personal_info_contract_address = (
"0x1234567890aBcDFE1234567890abcDFE12345679"
)
+ mock_token.require_personal_info_registered = True
mock_token.interest_payment_date = [
"interestPaymentDate1_test1",
"interestPaymentDate2_test1",
@@ -147,13 +148,14 @@ def test_normal_1(self, mock_get, client, db):
"is_offering": False,
"tradable_exchange_contract_address": "0x1234567890abCdFe1234567890ABCdFE12345678",
"personal_info_contract_address": "0x1234567890aBcDFE1234567890abcDFE12345679",
+ "require_personal_info_registered": True,
"contact_information": "contactInformation_test1",
"privacy_policy": "privacyPolicy_test1",
"issue_datetime": _issue_datetime,
"token_status": 1,
"transfer_approval_required": True,
"memo": "memo_test1",
- "contract_version": TokenVersion.V_23_12,
+ "contract_version": TokenVersion.V_24_06,
}
assert resp.status_code == 200
@@ -170,7 +172,7 @@ def test_normal_2(self, mock_get, client, db):
token.issuer_address = "issuer_address_test1"
token.token_address = "token_address_test1"
token.abi = "abi_test1"
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -211,6 +213,7 @@ def test_normal_2(self, mock_get, client, db):
mock_token.personal_info_contract_address = (
"0x1234567890aBcDFE1234567890abcDFE12345679"
)
+ mock_token.require_personal_info_registered = True
mock_token.interest_payment_date = [
"interestPaymentDate1_test1",
"interestPaymentDate2_test1",
@@ -271,13 +274,14 @@ def test_normal_2(self, mock_get, client, db):
"is_offering": False,
"tradable_exchange_contract_address": "0x1234567890abCdFe1234567890ABCdFE12345678",
"personal_info_contract_address": "0x1234567890aBcDFE1234567890abcDFE12345679",
+ "require_personal_info_registered": True,
"contact_information": "contactInformation_test1",
"privacy_policy": "privacyPolicy_test1",
"issue_datetime": _issue_datetime,
"token_status": 1,
"transfer_approval_required": True,
"memo": "memo_test1",
- "contract_version": TokenVersion.V_23_12,
+ "contract_version": TokenVersion.V_24_06,
}
assert resp.status_code == 200
@@ -309,7 +313,7 @@ def test_error_2(self, client, db):
token.token_address = "token_address_test1"
token.abi = "abi_test1"
token.token_status = 0
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_POST.py b/tests/app/test_bond_tokens_{token_address}_POST.py
similarity index 92%
rename from tests/test_app_routers_bond_tokens_{token_address}_POST.py
rename to tests/app/test_bond_tokens_{token_address}_POST.py
index 5c0402af..a32af693 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_POST.py
+++ b/tests/app/test_bond_tokens_{token_address}_POST.py
@@ -25,7 +25,7 @@
from eth_keyfile import decode_keyfile_json
from sqlalchemy import select
from web3 import Web3
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
import config
from app.exceptions import SendTransactionError
@@ -45,7 +45,7 @@
from tests.account_config import config_eth_account
web3 = Web3(Web3.HTTPProvider(config.WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
async def deploy_bond_token_contract(
@@ -110,7 +110,7 @@ async def test_normal_1_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -131,6 +131,7 @@ async def test_normal_1_1(self, client, db):
"is_redeemed": True,
"tradable_exchange_contract_address": "0xe883A6f441Ad5682d37DF31d34fc012bcB07A740",
"personal_info_contract_address": "0xa4CEe3b909751204AA151860ebBE8E7A851c2A1a",
+ "require_personal_info_registered": False,
"contact_information": "問い合わせ先test",
"privacy_policy": "プライバシーポリシーtest",
"transfer_approval_required": True,
@@ -175,6 +176,7 @@ async def test_normal_1_1(self, client, db):
"privacy_policy": "",
"status": True,
"personal_info_contract_address": "0x0000000000000000000000000000000000000000",
+ "require_personal_info_registered": True,
"transferable": False,
"is_offering": False,
"transfer_approval_required": False,
@@ -208,6 +210,7 @@ async def test_normal_1_1(self, client, db):
"is_redeemed": True,
"tradable_exchange_contract_address": "0xe883A6f441Ad5682d37DF31d34fc012bcB07A740",
"personal_info_contract_address": "0xa4CEe3b909751204AA151860ebBE8E7A851c2A1a",
+ "require_personal_info_registered": False,
"contact_information": "問い合わせ先test",
"privacy_policy": "プライバシーポリシーtest",
"transfer_approval_required": True,
@@ -246,7 +249,7 @@ async def test_normal_1_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -267,6 +270,7 @@ async def test_normal_1_2(self, client, db):
"is_redeemed": True,
"tradable_exchange_contract_address": "0xe883A6f441Ad5682d37DF31d34fc012bcB07A740",
"personal_info_contract_address": "0xa4CEe3b909751204AA151860ebBE8E7A851c2A1a",
+ "require_personal_info_registered": False,
"contact_information": "問い合わせ先test",
"privacy_policy": "プライバシーポリシーtest",
"transfer_approval_required": True,
@@ -311,6 +315,7 @@ async def test_normal_1_2(self, client, db):
"privacy_policy": "",
"status": True,
"personal_info_contract_address": "0x0000000000000000000000000000000000000000",
+ "require_personal_info_registered": True,
"transferable": False,
"is_offering": False,
"transfer_approval_required": False,
@@ -344,6 +349,7 @@ async def test_normal_1_2(self, client, db):
"is_redeemed": True,
"tradable_exchange_contract_address": "0xe883A6f441Ad5682d37DF31d34fc012bcB07A740",
"personal_info_contract_address": "0xa4CEe3b909751204AA151860ebBE8E7A851c2A1a",
+ "require_personal_info_registered": False,
"contact_information": "問い合わせ先test",
"privacy_policy": "プライバシーポリシーtest",
"transfer_approval_required": True,
@@ -382,7 +388,7 @@ async def test_normal_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -450,7 +456,7 @@ async def test_normal_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -515,6 +521,7 @@ async def test_normal_3(self, client, db):
"privacy_policy": "",
"status": True,
"personal_info_contract_address": "0x0000000000000000000000000000000000000000",
+ "require_personal_info_registered": True,
"transferable": False,
"is_offering": False,
"transfer_approval_required": False,
@@ -1228,7 +1235,7 @@ def test_error_7(self, IbetStraightBondContract_mock, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# mock
@@ -1350,7 +1357,7 @@ def test_error_10(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -1398,7 +1405,7 @@ def test_error_11(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -1420,3 +1427,97 @@ def test_error_11(self, client, db):
"meta": {"code": 2, "title": "SendTransactionError"},
"detail": "failed to send transaction",
}
+
+ #
+ # OperationNotSupportedVersionError: v23.12
+ def test_error_12_1(self, client, db):
+ test_account = config_eth_account("user1")
+ _issuer_address = test_account["address"]
+ _keyfile = test_account["keyfile_json"]
+ _token_address = "0x82b1c9374aB625380bd498a3d9dF4033B8A0E3Bb"
+
+ # prepare data
+ account = Account()
+ account.issuer_address = _issuer_address
+ account.keyfile = _keyfile
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.tx_hash = ""
+ token.issuer_address = _issuer_address
+ token.token_address = _token_address
+ token.abi = ""
+ token.token_status = 1
+ token.version = TokenVersion.V_22_12
+ db.add(token)
+
+ db.commit()
+
+ # request target API
+ req_param = {
+ "base_fx_rate": 10.0,
+ }
+ resp = client.post(
+ self.base_url.format(_token_address),
+ json=req_param,
+ headers={
+ "issuer-address": _issuer_address,
+ "eoa-password": E2EEUtils.encrypt("password"),
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 400
+ assert resp.json() == {
+ "meta": {"code": 6, "title": "OperationNotSupportedVersionError"},
+ "detail": "the operation is not supported in 22_12",
+ }
+
+ #
+ # OperationNotSupportedVersionError: v24.6
+ def test_error_12_2(self, client, db):
+ test_account = config_eth_account("user1")
+ _issuer_address = test_account["address"]
+ _keyfile = test_account["keyfile_json"]
+ _token_address = "0x82b1c9374aB625380bd498a3d9dF4033B8A0E3Bb"
+
+ # prepare data
+ account = Account()
+ account.issuer_address = _issuer_address
+ account.keyfile = _keyfile
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.tx_hash = ""
+ token.issuer_address = _issuer_address
+ token.token_address = _token_address
+ token.abi = ""
+ token.token_status = 1
+ token.version = TokenVersion.V_23_12
+ db.add(token)
+
+ db.commit()
+
+ # request target API
+ req_param = {
+ "require_personal_info_registered": True,
+ }
+ resp = client.post(
+ self.base_url.format(_token_address),
+ json=req_param,
+ headers={
+ "issuer-address": _issuer_address,
+ "eoa-password": E2EEUtils.encrypt("password"),
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 400
+ assert resp.json() == {
+ "meta": {"code": 6, "title": "OperationNotSupportedVersionError"},
+ "detail": "the operation is not supported in 23_12",
+ }
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_additional_issue_GET.py b/tests/app/test_bond_tokens_{token_address}_additional_issue_GET.py
similarity index 98%
rename from tests/test_app_routers_bond_tokens_{token_address}_additional_issue_GET.py
rename to tests/app/test_bond_tokens_{token_address}_additional_issue_GET.py
index b6478bc5..cf900881 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_additional_issue_GET.py
+++ b/tests/app/test_bond_tokens_{token_address}_additional_issue_GET.py
@@ -74,7 +74,7 @@ def test_normal_1(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXIssueRedeem
@@ -110,7 +110,7 @@ def test_normal_2(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXIssueRedeem
@@ -191,7 +191,7 @@ def test_normal_3(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXIssueRedeem
@@ -278,7 +278,7 @@ def test_normal_4(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXIssueRedeem
@@ -365,7 +365,7 @@ def test_error_2(self, client, db):
_token.token_address = self.test_token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -425,7 +425,7 @@ def test_error_4_1(self, client, db):
"detail": [
{
"ctx": {"expected": "0 or 1"},
- "input": -1,
+ "input": "-1",
"loc": ["query", "sort_order"],
"msg": "Input should be 0 or 1",
"type": "enum",
@@ -449,7 +449,7 @@ def test_error_4_2(self, client, db):
"detail": [
{
"ctx": {"expected": "0 or 1"},
- "input": 2,
+ "input": "2",
"loc": ["query", "sort_order"],
"msg": "Input should be 0 or 1",
"type": "enum",
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_additional_issue_POST.py b/tests/app/test_bond_tokens_{token_address}_additional_issue_POST.py
similarity index 98%
rename from tests/test_app_routers_bond_tokens_{token_address}_additional_issue_POST.py
rename to tests/app/test_bond_tokens_{token_address}_additional_issue_POST.py
index f922ff8e..fedbc5d7 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_additional_issue_POST.py
+++ b/tests/app/test_bond_tokens_{token_address}_additional_issue_POST.py
@@ -58,7 +58,7 @@ def test_normal_1(self, IbetStraightBondContract_mock, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -115,7 +115,7 @@ def test_normal_2(self, IbetStraightBondContract_mock, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -163,7 +163,7 @@ def test_error_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -210,7 +210,7 @@ def test_error_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -257,7 +257,7 @@ def test_error_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -400,7 +400,7 @@ def test_error_7(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -514,7 +514,7 @@ def test_error_10(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -562,7 +562,7 @@ def test_error_11(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_additional_issue_batch_GET.py b/tests/app/test_bond_tokens_{token_address}_additional_issue_batch_GET.py
similarity index 98%
rename from tests/test_app_routers_bond_tokens_{token_address}_additional_issue_batch_GET.py
rename to tests/app/test_bond_tokens_{token_address}_additional_issue_batch_GET.py
index ec0ced69..b464a9f2 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_additional_issue_batch_GET.py
+++ b/tests/app/test_bond_tokens_{token_address}_additional_issue_batch_GET.py
@@ -52,7 +52,7 @@ def test_normal_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# request target API
@@ -78,7 +78,7 @@ def test_normal_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
additional_issue_upload1 = BatchIssueRedeemUpload()
@@ -127,7 +127,7 @@ def test_normal_3_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
additional_issue_upload1 = BatchIssueRedeemUpload()
@@ -244,7 +244,7 @@ def test_normal_3_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
additional_issue_upload1 = BatchIssueRedeemUpload()
@@ -348,7 +348,7 @@ def test_normal_3_3(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
additional_issue_upload1 = BatchIssueRedeemUpload()
@@ -458,7 +458,7 @@ def test_normal_4(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
additional_issue_upload1 = BatchIssueRedeemUpload()
@@ -560,7 +560,7 @@ def test_normal_5(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
additional_issue_upload1 = BatchIssueRedeemUpload()
@@ -683,7 +683,7 @@ def test_error_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_additional_issue_batch_POST.py b/tests/app/test_bond_tokens_{token_address}_additional_issue_batch_POST.py
similarity index 97%
rename from tests/test_app_routers_bond_tokens_{token_address}_additional_issue_batch_POST.py
rename to tests/app/test_bond_tokens_{token_address}_additional_issue_batch_POST.py
index 39420237..1402f7e0 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_additional_issue_batch_POST.py
+++ b/tests/app/test_bond_tokens_{token_address}_additional_issue_batch_POST.py
@@ -66,7 +66,7 @@ def test_normal_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -131,7 +131,7 @@ def test_normal_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -206,7 +206,7 @@ def test_error_1_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -258,7 +258,7 @@ def test_error_1_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -313,7 +313,7 @@ def test_error_1_3_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -368,7 +368,7 @@ def test_error_1_3_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -423,7 +423,7 @@ def test_error_1_4(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -472,7 +472,7 @@ def test_error_1_5(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -521,7 +521,7 @@ def test_error_1_6(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -568,7 +568,7 @@ def test_error_1_7_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -615,7 +615,7 @@ def test_error_1_7_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -703,7 +703,7 @@ def test_error_1_8_2(self, client, db):
token.token_address = token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_additional_issue_batch_{batch_id}_GET.py b/tests/app/test_bond_tokens_{token_address}_additional_issue_batch_{batch_id}_GET.py
similarity index 98%
rename from tests/test_app_routers_bond_tokens_{token_address}_additional_issue_batch_{batch_id}_GET.py
rename to tests/app/test_bond_tokens_{token_address}_additional_issue_batch_{batch_id}_GET.py
index e85984a6..77c99428 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_additional_issue_batch_{batch_id}_GET.py
+++ b/tests/app/test_bond_tokens_{token_address}_additional_issue_batch_{batch_id}_GET.py
@@ -71,7 +71,7 @@ def test_normal_1_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = test_token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
batch_upload = BatchIssueRedeemUpload()
@@ -158,7 +158,7 @@ def test_normal_1_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = test_token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
batch_upload = BatchIssueRedeemUpload()
@@ -245,7 +245,7 @@ def test_normal_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = test_token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
batch_upload = BatchIssueRedeemUpload()
@@ -358,7 +358,7 @@ def test_error_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = test_token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
batch_upload = BatchIssueRedeemUpload()
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_history_GET.py b/tests/app/test_bond_tokens_{token_address}_history_GET.py
similarity index 96%
rename from tests/test_app_routers_bond_tokens_{token_address}_history_GET.py
rename to tests/app/test_bond_tokens_{token_address}_history_GET.py
index 80523de8..41345770 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_history_GET.py
+++ b/tests/app/test_bond_tokens_{token_address}_history_GET.py
@@ -28,7 +28,7 @@
from starlette.testclient import TestClient
from web3 import Web3
from web3.contract import Contract
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
import config
from app.model.blockchain import IbetStraightBondContract
@@ -46,7 +46,7 @@
from tests.account_config import config_eth_account
web3 = Web3(Web3.HTTPProvider(config.WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
async def deploy_bond_token_contract(
@@ -94,6 +94,7 @@ async def deploy_bond_token_contract(
is_offering=True, # update
tradable_exchange_contract_address=tradable_exchange_contract_address, # update
personal_info_contract_address=personal_info_contract_address, # update
+ require_personal_info_registered=False, # update
image_url=None,
contact_information="contact info test", # update
privacy_policy="privacy policy test", # update
@@ -157,6 +158,10 @@ async def deploy_bond_token_contract(
token_create_param["personal_info_contract_address"]
).build_transaction(build_tx_param)
ContractUtils.send_transaction(transaction=tx, private_key=private_key)
+ tx = contract.functions.setRequirePersonalInfoRegistered(
+ token_create_param["require_personal_info_registered"]
+ ).build_transaction(build_tx_param)
+ ContractUtils.send_transaction(transaction=tx, private_key=private_key)
tx = contract.functions.setContactInformation(
token_create_param["contact_information"]
).build_transaction(build_tx_param)
@@ -272,7 +277,7 @@ def test_normal_1(self, client, db, personal_info_contract):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -325,7 +330,7 @@ async def test_normal_2(self, client, db, personal_info_contract):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -416,7 +421,7 @@ async def test_normal_3_1(self, client, db, personal_info_contract):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -505,7 +510,7 @@ async def test_normal_3_2(self, client, db, personal_info_contract):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -585,7 +590,7 @@ async def test_normal_3_3(self, client, db, personal_info_contract, monkeypatch)
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_operation_log_1 = TokenUpdateOperationLog()
@@ -622,7 +627,7 @@ async def test_normal_3_3(self, client, db, personal_info_contract, monkeypatch)
resp = client.get(
self.base_url.format(_token_address),
params={
- "created_from": str(datetime(2023, 5, 3, 8, 0, 0)),
+ "created_from": "2023-05-03 08:00:00",
},
)
@@ -644,13 +649,13 @@ async def test_normal_3_3(self, client, db, personal_info_contract, monkeypatch)
"original_contents": {},
"modified_contents": {"memo": "20230504"},
"operation_category": TokenUpdateOperationCategory.UPDATE.value,
- "created": ANY,
+ "created": "2023-05-04T09:00:00+09:00",
},
{
"original_contents": {},
"modified_contents": {"memo": "20230503"},
"operation_category": TokenUpdateOperationCategory.UPDATE.value,
- "created": ANY,
+ "created": "2023-05-03T09:00:00+09:00",
},
],
}
@@ -690,7 +695,7 @@ async def test_normal_3_4(self, client, db, personal_info_contract, monkeypatch)
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_operation_log_1 = TokenUpdateOperationLog()
@@ -727,7 +732,7 @@ async def test_normal_3_4(self, client, db, personal_info_contract, monkeypatch)
resp = client.get(
self.base_url.format(_token_address),
params={
- "created_to": str(datetime(2023, 5, 2, 0, 0, 0)),
+ "created_to": "2023-05-02 00:00:00",
},
)
@@ -745,7 +750,7 @@ async def test_normal_3_4(self, client, db, personal_info_contract, monkeypatch)
"original_contents": None,
"modified_contents": create_param,
"operation_category": TokenUpdateOperationCategory.ISSUE.value,
- "created": ANY,
+ "created": "2023-05-01T09:00:00+09:00",
},
],
}
@@ -781,7 +786,7 @@ async def test_normal_4_1(self, client, db, personal_info_contract):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -876,7 +881,7 @@ async def test_normal_4_2(self, client, db, personal_info_contract):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -972,7 +977,7 @@ async def test_normal_5_1(self, client, db, personal_info_contract):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -1052,7 +1057,7 @@ async def test_normal_5_2(self, client, db, personal_info_contract):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -1109,39 +1114,37 @@ def test_error_1(self, client, db):
"meta": {"code": 1, "title": "RequestValidationError"},
"detail": [
{
- "ctx": {"expected": "'Issue' or 'Update'"},
- "input": "test",
+ "type": "enum",
"loc": ["query", "operation_category"],
"msg": "Input should be 'Issue' or 'Update'",
- "type": "enum",
+ "input": "test",
+ "ctx": {"expected": "'Issue' or 'Update'"},
},
{
- "ctx": {"expected": "'created' or 'operation_category'"},
- "input": "test",
+ "type": "enum",
"loc": ["query", "sort_item"],
"msg": "Input should be 'created' or 'operation_category'",
- "type": "enum",
+ "input": "test",
+ "ctx": {"expected": "'created' or 'operation_category'"},
},
{
- "input": "test",
+ "type": "enum",
"loc": ["query", "sort_order"],
- "msg": "Input should be a valid integer, unable to parse string "
- "as an integer",
- "type": "int_parsing",
+ "msg": "Input should be 0 or 1",
+ "input": "test",
+ "ctx": {"expected": "0 or 1"},
},
{
- "input": "test",
- "loc": ["query", "offset"],
- "msg": "Input should be a valid integer, unable to parse string "
- "as an integer",
"type": "int_parsing",
+ "loc": ["query", "offset"],
+ "msg": "Input should be a valid integer, unable to parse string as an integer",
+ "input": "test",
},
{
- "input": "test",
- "loc": ["query", "limit"],
- "msg": "Input should be a valid integer, unable to parse string "
- "as an integer",
"type": "int_parsing",
+ "loc": ["query", "limit"],
+ "msg": "Input should be a valid integer, unable to parse string as an integer",
+ "input": "test",
},
],
}
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_holders_GET.py b/tests/app/test_bond_tokens_{token_address}_holders_GET.py
similarity index 85%
rename from tests/test_app_routers_bond_tokens_{token_address}_holders_GET.py
rename to tests/app/test_bond_tokens_{token_address}_holders_GET.py
index 50d4854b..e7d53cb1 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_holders_GET.py
+++ b/tests/app/test_bond_tokens_{token_address}_holders_GET.py
@@ -57,7 +57,7 @@ def test_normal_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -95,7 +95,7 @@ def test_normal_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: Position
@@ -212,7 +212,7 @@ def test_normal_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -441,7 +441,7 @@ def test_normal_4_1_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -576,7 +576,7 @@ def test_normal_4_1_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
idx_position_1 = IDXPosition()
@@ -733,7 +733,7 @@ def test_normal_4_2_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -925,7 +925,7 @@ def test_normal_4_2_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -1136,7 +1136,7 @@ def test_normal_4_2_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -1347,7 +1347,7 @@ def test_normal_4_3_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -1539,7 +1539,7 @@ def test_normal_4_3_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -1750,7 +1750,7 @@ def test_normal_4_3_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -1961,7 +1961,7 @@ def test_normal_4_4_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -2153,7 +2153,7 @@ def test_normal_4_4_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -2353,6 +2353,7 @@ def test_normal_4_4_3(self, client, db):
_account_address_1 = "0xb75c7545b9230FEe99b7af370D38eBd3DAD929f7"
_account_address_2 = "0x3F198534Bbe3B2a197d3B317d41392F348EAC707"
_account_address_3 = "0x8277D905F37F8a9717F5718d0daC21495dFE74bf"
+ _account_address_4 = "0x1CBd3b2770909D4e10f157cABC84C7264073C9Ec"
account = Account()
account.issuer_address = _issuer_address
@@ -2364,7 +2365,7 @@ def test_normal_4_4_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -2500,6 +2501,17 @@ def test_normal_4_4_3(self, client, db):
}
db.add(idx_personal_info_3)
+ # prepare data: account_address_4
+ idx_position_4 = IDXPosition()
+ idx_position_4.token_address = _token_address
+ idx_position_4.account_address = _account_address_4
+ idx_position_4.balance = 99
+ idx_position_4.exchange_balance = 99
+ idx_position_4.exchange_commitment = 99
+ idx_position_4.pending_transfer = 99
+ idx_position_4.modified = datetime(2023, 10, 24, 3, 0, 0)
+ db.add(idx_position_4)
+
db.commit()
# request target API
@@ -2512,7 +2524,7 @@ def test_normal_4_4_3(self, client, db):
# assertion
assert resp.status_code == 200
assert resp.json() == {
- "result_set": {"count": 2, "total": 3, "offset": None, "limit": None},
+ "result_set": {"count": 3, "limit": None, "offset": None, "total": 4},
"holders": [
{
"account_address": _account_address_1,
@@ -2545,19 +2557,642 @@ def test_normal_4_4_3(self, client, db):
"is_corporate": None,
"tax_category": None,
},
- "balance": 20,
- "exchange_balance": 21,
- "exchange_commitment": 22,
- "pending_transfer": 10,
- "locked": 20,
- "modified": "2023-10-24T02:20:00",
+ "balance": 20,
+ "exchange_balance": 21,
+ "exchange_commitment": 22,
+ "pending_transfer": 10,
+ "locked": 20,
+ "modified": "2023-10-24T02:20:00",
+ },
+ {
+ "account_address": _account_address_4,
+ "pending_transfer": 99,
+ "personal_information": {
+ "address": None,
+ "birth": None,
+ "email": None,
+ "is_corporate": None,
+ "key_manager": None,
+ "name": None,
+ "postal_code": None,
+ "tax_category": None,
+ },
+ "balance": 99,
+ "exchange_balance": 99,
+ "exchange_commitment": 99,
+ "locked": 0,
+ "modified": "2023-10-24T03:00:00",
+ },
+ ],
+ }
+
+ #
+ # Search filter: balance + pending_transfer & "="
+ def test_normal_4_5_1(self, client, db):
+ user = config_eth_account("user1")
+ _issuer_address = user["address"]
+ _token_address = "0x82b1c9374aB625380bd498a3d9dF4033B8A0E3Bb"
+ _account_address_1 = "0xb75c7545b9230FEe99b7af370D38eBd3DAD929f7"
+ _account_address_2 = "0x3F198534Bbe3B2a197d3B317d41392F348EAC707"
+ _account_address_3 = "0x8277D905F37F8a9717F5718d0daC21495dFE74bf"
+
+ account = Account()
+ account.issuer_address = _issuer_address
+ db.add(account)
+
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.tx_hash = ""
+ token.issuer_address = _issuer_address
+ token.token_address = _token_address
+ token.abi = ""
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ # prepare data: account_address_1
+ idx_position_1 = IDXPosition()
+ idx_position_1.token_address = _token_address
+ idx_position_1.account_address = _account_address_1
+ idx_position_1.balance = 10
+ idx_position_1.exchange_balance = 11
+ idx_position_1.exchange_commitment = 12
+ idx_position_1.pending_transfer = 5
+ idx_position_1.modified = datetime(2023, 10, 24, 0, 0, 0)
+ db.add(idx_position_1)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_1
+ idx_locked_position.value = 5
+ idx_locked_position.modified = datetime(2023, 10, 24, 1, 0, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_1
+ idx_locked_position.value = 5
+ idx_locked_position.modified = datetime(2023, 10, 24, 1, 10, 0)
+ db.add(idx_locked_position)
+
+ idx_personal_info_1 = IDXPersonalInfo()
+ idx_personal_info_1.account_address = _account_address_1
+ idx_personal_info_1.issuer_address = _issuer_address
+ idx_personal_info_1.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ db.add(idx_personal_info_1)
+
+ # prepare data: account_address_2
+ idx_position_2 = IDXPosition()
+ idx_position_2.token_address = _token_address
+ idx_position_2.account_address = _account_address_2
+ idx_position_2.balance = 20
+ idx_position_2.exchange_balance = 21
+ idx_position_2.exchange_commitment = 22
+ idx_position_2.pending_transfer = 10
+ idx_position_2.modified = datetime(2023, 10, 24, 2, 0, 0)
+ db.add(idx_position_2)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_2
+ idx_locked_position.value = 10
+ idx_locked_position.modified = datetime(2023, 10, 24, 2, 10, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_2
+ idx_locked_position.value = 10
+ idx_locked_position.modified = datetime(2023, 10, 24, 2, 20, 0)
+ db.add(idx_locked_position)
+
+ # prepare data: account_address_3
+ idx_position_3 = IDXPosition()
+ idx_position_3.token_address = _token_address
+ idx_position_3.account_address = _account_address_3
+ idx_position_3.balance = 99
+ idx_position_3.exchange_balance = 99
+ idx_position_3.exchange_commitment = 99
+ idx_position_3.pending_transfer = 99
+ idx_position_3.modified = datetime(2023, 10, 24, 3, 0, 0)
+ db.add(idx_position_3)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_3
+ idx_locked_position.value = 15
+ idx_locked_position.modified = datetime(2023, 10, 24, 4, 0, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_3
+ idx_locked_position.value = 15
+ idx_locked_position.modified = datetime(2023, 10, 24, 5, 0, 0)
+ db.add(idx_locked_position)
+
+ # Other locked position
+ _locked_position = IDXLockedPosition()
+ _locked_position.token_address = "other_token_address"
+ _locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ _locked_position.account_address = _account_address_1
+ _locked_position.value = 5
+ _locked_position.modified = datetime(2023, 10, 25, 0, 2, 0)
+ db.add(_locked_position)
+
+ idx_personal_info_3 = IDXPersonalInfo()
+ idx_personal_info_3.account_address = _account_address_3
+ idx_personal_info_3.issuer_address = _issuer_address
+ idx_personal_info_3.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": "birth_test3",
+ # PersonalInfo is partially registered.
+ }
+ db.add(idx_personal_info_3)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(_token_address),
+ headers={"issuer-address": _issuer_address},
+ params={
+ "balance_and_pending_transfer": 30,
+ "balance_and_pending_transfer_operator": 0,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 1, "total": 3, "offset": None, "limit": None},
+ "holders": [
+ {
+ "account_address": _account_address_2,
+ "personal_information": {
+ "key_manager": None,
+ "name": None,
+ "postal_code": None,
+ "address": None,
+ "email": None,
+ "birth": None,
+ "is_corporate": None,
+ "tax_category": None,
+ },
+ "balance": 20,
+ "exchange_balance": 21,
+ "exchange_commitment": 22,
+ "pending_transfer": 10,
+ "locked": 20,
+ "modified": "2023-10-24T02:20:00",
+ },
+ ],
+ }
+
+ #
+ # Search filter: balance + pending_transfer & ">="
+ def test_normal_4_5_2(self, client, db):
+ user = config_eth_account("user1")
+ _issuer_address = user["address"]
+ _token_address = "0x82b1c9374aB625380bd498a3d9dF4033B8A0E3Bb"
+ _account_address_1 = "0xb75c7545b9230FEe99b7af370D38eBd3DAD929f7"
+ _account_address_2 = "0x3F198534Bbe3B2a197d3B317d41392F348EAC707"
+ _account_address_3 = "0x8277D905F37F8a9717F5718d0daC21495dFE74bf"
+
+ account = Account()
+ account.issuer_address = _issuer_address
+ db.add(account)
+
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.tx_hash = ""
+ token.issuer_address = _issuer_address
+ token.token_address = _token_address
+ token.abi = ""
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ # prepare data: account_address_1
+ idx_position_1 = IDXPosition()
+ idx_position_1.token_address = _token_address
+ idx_position_1.account_address = _account_address_1
+ idx_position_1.balance = 10
+ idx_position_1.exchange_balance = 11
+ idx_position_1.exchange_commitment = 12
+ idx_position_1.pending_transfer = 5
+ idx_position_1.modified = datetime(2023, 10, 24, 0, 0, 0)
+ db.add(idx_position_1)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_1
+ idx_locked_position.value = 5
+ idx_locked_position.modified = datetime(2023, 10, 24, 1, 0, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_1
+ idx_locked_position.value = 5
+ idx_locked_position.modified = datetime(2023, 10, 24, 1, 10, 0)
+ db.add(idx_locked_position)
+
+ idx_personal_info_1 = IDXPersonalInfo()
+ idx_personal_info_1.account_address = _account_address_1
+ idx_personal_info_1.issuer_address = _issuer_address
+ idx_personal_info_1.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ db.add(idx_personal_info_1)
+
+ # prepare data: account_address_2
+ idx_position_2 = IDXPosition()
+ idx_position_2.token_address = _token_address
+ idx_position_2.account_address = _account_address_2
+ idx_position_2.balance = 20
+ idx_position_2.exchange_balance = 21
+ idx_position_2.exchange_commitment = 22
+ idx_position_2.pending_transfer = 10
+ idx_position_2.modified = datetime(2023, 10, 24, 2, 0, 0)
+ db.add(idx_position_2)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_2
+ idx_locked_position.value = 10
+ idx_locked_position.modified = datetime(2023, 10, 24, 2, 10, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_2
+ idx_locked_position.value = 10
+ idx_locked_position.modified = datetime(2023, 10, 24, 2, 20, 0)
+ db.add(idx_locked_position)
+
+ # prepare data: account_address_3
+ idx_position_3 = IDXPosition()
+ idx_position_3.token_address = _token_address
+ idx_position_3.account_address = _account_address_3
+ idx_position_3.balance = 99
+ idx_position_3.exchange_balance = 99
+ idx_position_3.exchange_commitment = 99
+ idx_position_3.pending_transfer = 99
+ idx_position_3.modified = datetime(2023, 10, 24, 3, 0, 0)
+ db.add(idx_position_3)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_3
+ idx_locked_position.value = 15
+ idx_locked_position.modified = datetime(2023, 10, 24, 4, 0, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_3
+ idx_locked_position.value = 15
+ idx_locked_position.modified = datetime(2023, 10, 24, 5, 0, 0)
+ db.add(idx_locked_position)
+
+ # Other locked position
+ _locked_position = IDXLockedPosition()
+ _locked_position.token_address = "other_token_address"
+ _locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ _locked_position.account_address = _account_address_1
+ _locked_position.value = 5
+ _locked_position.modified = datetime(2023, 10, 25, 0, 2, 0)
+ db.add(_locked_position)
+
+ idx_personal_info_3 = IDXPersonalInfo()
+ idx_personal_info_3.account_address = _account_address_3
+ idx_personal_info_3.issuer_address = _issuer_address
+ idx_personal_info_3.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": "birth_test3",
+ # PersonalInfo is partially registered.
+ }
+ db.add(idx_personal_info_3)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(_token_address),
+ headers={"issuer-address": _issuer_address},
+ params={
+ "balance_and_pending_transfer": 30,
+ "balance_and_pending_transfer_operator": 1,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 2, "total": 3, "offset": None, "limit": None},
+ "holders": [
+ {
+ "account_address": _account_address_2,
+ "personal_information": {
+ "key_manager": None,
+ "name": None,
+ "postal_code": None,
+ "address": None,
+ "email": None,
+ "birth": None,
+ "is_corporate": None,
+ "tax_category": None,
+ },
+ "balance": 20,
+ "exchange_balance": 21,
+ "exchange_commitment": 22,
+ "pending_transfer": 10,
+ "locked": 20,
+ "modified": "2023-10-24T02:20:00",
+ },
+ {
+ "account_address": _account_address_3,
+ "personal_information": {
+ "key_manager": "key_manager_test1",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": "birth_test3",
+ "is_corporate": None,
+ "tax_category": None,
+ },
+ "balance": 99,
+ "exchange_balance": 99,
+ "exchange_commitment": 99,
+ "pending_transfer": 99,
+ "locked": 30,
+ "modified": "2023-10-24T05:00:00",
+ },
+ ],
+ }
+
+ #
+ # Search filter: balance + pending_transfer & "<="
+ def test_normal_4_5_3(self, client, db):
+ user = config_eth_account("user1")
+ _issuer_address = user["address"]
+ _token_address = "0x82b1c9374aB625380bd498a3d9dF4033B8A0E3Bb"
+ _account_address_1 = "0xb75c7545b9230FEe99b7af370D38eBd3DAD929f7"
+ _account_address_2 = "0x3F198534Bbe3B2a197d3B317d41392F348EAC707"
+ _account_address_3 = "0x8277D905F37F8a9717F5718d0daC21495dFE74bf"
+
+ account = Account()
+ account.issuer_address = _issuer_address
+ db.add(account)
+
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.tx_hash = ""
+ token.issuer_address = _issuer_address
+ token.token_address = _token_address
+ token.abi = ""
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ # prepare data: account_address_1
+ idx_position_1 = IDXPosition()
+ idx_position_1.token_address = _token_address
+ idx_position_1.account_address = _account_address_1
+ idx_position_1.balance = 10
+ idx_position_1.exchange_balance = 11
+ idx_position_1.exchange_commitment = 12
+ idx_position_1.pending_transfer = 5
+ idx_position_1.modified = datetime(2023, 10, 24, 0, 0, 0)
+ db.add(idx_position_1)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_1
+ idx_locked_position.value = 5
+ idx_locked_position.modified = datetime(2023, 10, 24, 1, 0, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_1
+ idx_locked_position.value = 5
+ idx_locked_position.modified = datetime(2023, 10, 24, 1, 10, 0)
+ db.add(idx_locked_position)
+
+ idx_personal_info_1 = IDXPersonalInfo()
+ idx_personal_info_1.account_address = _account_address_1
+ idx_personal_info_1.issuer_address = _issuer_address
+ idx_personal_info_1.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ db.add(idx_personal_info_1)
+
+ # prepare data: account_address_2
+ idx_position_2 = IDXPosition()
+ idx_position_2.token_address = _token_address
+ idx_position_2.account_address = _account_address_2
+ idx_position_2.balance = 20
+ idx_position_2.exchange_balance = 21
+ idx_position_2.exchange_commitment = 22
+ idx_position_2.pending_transfer = 10
+ idx_position_2.modified = datetime(2023, 10, 24, 2, 0, 0)
+ db.add(idx_position_2)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_2
+ idx_locked_position.value = 10
+ idx_locked_position.modified = datetime(2023, 10, 24, 2, 10, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_2
+ idx_locked_position.value = 10
+ idx_locked_position.modified = datetime(2023, 10, 24, 2, 20, 0)
+ db.add(idx_locked_position)
+
+ # prepare data: account_address_3
+ idx_position_3 = IDXPosition()
+ idx_position_3.token_address = _token_address
+ idx_position_3.account_address = _account_address_3
+ idx_position_3.balance = 99
+ idx_position_3.exchange_balance = 99
+ idx_position_3.exchange_commitment = 99
+ idx_position_3.pending_transfer = 99
+ idx_position_3.modified = datetime(2023, 10, 24, 3, 0, 0)
+ db.add(idx_position_3)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_3
+ idx_locked_position.value = 15
+ idx_locked_position.modified = datetime(2023, 10, 24, 4, 0, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_3
+ idx_locked_position.value = 15
+ idx_locked_position.modified = datetime(2023, 10, 24, 5, 0, 0)
+ db.add(idx_locked_position)
+
+ # Other locked position
+ _locked_position = IDXLockedPosition()
+ _locked_position.token_address = "other_token_address"
+ _locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ _locked_position.account_address = _account_address_1
+ _locked_position.value = 5
+ _locked_position.modified = datetime(2023, 10, 25, 0, 2, 0)
+ db.add(_locked_position)
+
+ idx_personal_info_3 = IDXPersonalInfo()
+ idx_personal_info_3.account_address = _account_address_3
+ idx_personal_info_3.issuer_address = _issuer_address
+ idx_personal_info_3.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": "birth_test3",
+ # PersonalInfo is partially registered.
+ }
+ db.add(idx_personal_info_3)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(_token_address),
+ headers={"issuer-address": _issuer_address},
+ params={
+ "balance_and_pending_transfer": 20,
+ "balance_and_pending_transfer_operator": 2,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 1, "total": 3, "offset": None, "limit": None},
+ "holders": [
+ {
+ "account_address": _account_address_1,
+ "personal_information": {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "balance": 10,
+ "exchange_balance": 11,
+ "exchange_commitment": 12,
+ "pending_transfer": 5,
+ "locked": 10,
+ "modified": "2023-10-24T01:10:00",
},
],
}
- #
+ #
# Search filter: holder_name
- def test_normal_4_5(self, client, db):
+ def test_normal_4_6(self, client, db):
user = config_eth_account("user1")
_issuer_address = user["address"]
_token_address = "0x82b1c9374aB625380bd498a3d9dF4033B8A0E3Bb"
@@ -2575,7 +3210,7 @@ def test_normal_4_5(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -2747,9 +3382,9 @@ def test_normal_4_5(self, client, db):
],
}
- #
+ #
# Search filter: key_manager
- def test_normal_4_6(self, client, db):
+ def test_normal_4_7(self, client, db):
user = config_eth_account("user1")
_issuer_address = user["address"]
_token_address = "0x82b1c9374aB625380bd498a3d9dF4033B8A0E3Bb"
@@ -2767,7 +3402,7 @@ def test_normal_4_6(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -2958,9 +3593,9 @@ def test_normal_4_6(self, client, db):
],
}
- #
+ #
# Search filter: account_address
- def test_normal_4_7(self, client, db):
+ def test_normal_4_8(self, client, db):
user = config_eth_account("user1")
_issuer_address = user["address"]
_token_address = "0x82b1c9374aB625380bd498a3d9dF4033B8A0E3Bb"
@@ -2978,7 +3613,7 @@ def test_normal_4_7(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -3170,7 +3805,7 @@ def test_normal_5_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -3403,7 +4038,7 @@ def test_normal_5_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -3636,7 +4271,7 @@ def test_normal_5_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -3869,7 +4504,7 @@ def test_normal_5_4(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -4102,7 +4737,7 @@ def test_normal_5_5(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -4316,7 +4951,7 @@ def test_normal_5_5(self, client, db):
}
#
- # Sort Item: holder_name
+ # Sort Item: balance + pending_transfer
def test_normal_5_6(self, client, db):
user = config_eth_account("user1")
_issuer_address = user["address"]
@@ -4324,6 +4959,239 @@ def test_normal_5_6(self, client, db):
_account_address_1 = "0xb75c7545b9230FEe99b7af370D38eBd3DAD929f7"
_account_address_2 = "0x3F198534Bbe3B2a197d3B317d41392F348EAC707"
_account_address_3 = "0x8277D905F37F8a9717F5718d0daC21495dFE74bf"
+
+ account = Account()
+ account.issuer_address = _issuer_address
+ db.add(account)
+
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.tx_hash = ""
+ token.issuer_address = _issuer_address
+ token.token_address = _token_address
+ token.abi = ""
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ # prepare data: account_address_1
+ idx_position_1 = IDXPosition()
+ idx_position_1.token_address = _token_address
+ idx_position_1.account_address = _account_address_1
+ idx_position_1.balance = 10
+ idx_position_1.exchange_balance = 11
+ idx_position_1.exchange_commitment = 12
+ idx_position_1.pending_transfer = 5
+ idx_position_1.created = datetime(2023, 10, 24, 0, 0, 0)
+ idx_position_1.modified = datetime(2023, 10, 24, 0, 0, 0)
+ db.add(idx_position_1)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_1
+ idx_locked_position.value = 5
+ idx_locked_position.modified = datetime(2023, 10, 24, 1, 0, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_1
+ idx_locked_position.value = 5
+ idx_locked_position.modified = datetime(2023, 10, 24, 1, 10, 0)
+ db.add(idx_locked_position)
+
+ idx_personal_info_1 = IDXPersonalInfo()
+ idx_personal_info_1.account_address = _account_address_1
+ idx_personal_info_1.issuer_address = _issuer_address
+ idx_personal_info_1.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ db.add(idx_personal_info_1)
+
+ # prepare data: account_address_2
+ idx_position_2 = IDXPosition()
+ idx_position_2.token_address = _token_address
+ idx_position_2.account_address = _account_address_2
+ idx_position_2.balance = 20
+ idx_position_2.exchange_balance = 21
+ idx_position_2.exchange_commitment = 22
+ idx_position_2.pending_transfer = 10
+ idx_position_2.created = datetime(2023, 10, 24, 2, 0, 0)
+ idx_position_2.modified = datetime(2023, 10, 24, 2, 0, 0)
+ db.add(idx_position_2)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_2
+ idx_locked_position.value = 10
+ idx_locked_position.modified = datetime(2023, 10, 24, 2, 10, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_2
+ idx_locked_position.value = 10
+ idx_locked_position.modified = datetime(2023, 10, 24, 2, 20, 0)
+ db.add(idx_locked_position)
+
+ # prepare data: account_address_3
+ idx_position_3 = IDXPosition()
+ idx_position_3.token_address = _token_address
+ idx_position_3.account_address = _account_address_3
+ idx_position_3.balance = 99
+ idx_position_3.exchange_balance = 99
+ idx_position_3.exchange_commitment = 99
+ idx_position_3.pending_transfer = 99
+ idx_position_3.created = datetime(2023, 10, 24, 3, 0, 0)
+ idx_position_3.modified = datetime(2023, 10, 24, 3, 0, 0)
+ db.add(idx_position_3)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_3
+ idx_locked_position.value = 15
+ idx_locked_position.modified = datetime(2023, 10, 24, 4, 0, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_3
+ idx_locked_position.value = 15
+ idx_locked_position.modified = datetime(2023, 10, 24, 5, 0, 0)
+ db.add(idx_locked_position)
+
+ # Other locked position
+ _locked_position = IDXLockedPosition()
+ _locked_position.token_address = "other_token_address"
+ _locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ _locked_position.account_address = _account_address_1
+ _locked_position.value = 5
+ _locked_position.modified = datetime(2023, 10, 25, 0, 2, 0)
+ db.add(_locked_position)
+
+ idx_personal_info_3 = IDXPersonalInfo()
+ idx_personal_info_3.account_address = _account_address_3
+ idx_personal_info_3.issuer_address = _issuer_address
+ idx_personal_info_3.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": "birth_test3",
+ # PersonalInfo is partially registered.
+ }
+ db.add(idx_personal_info_3)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(_token_address),
+ headers={"issuer-address": _issuer_address},
+ params={"sort_order": 1, "sort_item": "balance_and_pending_transfer"},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 3, "total": 3, "offset": None, "limit": None},
+ "holders": [
+ {
+ "account_address": _account_address_3,
+ "personal_information": {
+ "key_manager": "key_manager_test1",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": "birth_test3",
+ "is_corporate": None,
+ "tax_category": None,
+ },
+ "balance": 99,
+ "exchange_balance": 99,
+ "exchange_commitment": 99,
+ "pending_transfer": 99,
+ "locked": 30,
+ "modified": "2023-10-24T05:00:00",
+ },
+ {
+ "account_address": _account_address_2,
+ "personal_information": {
+ "key_manager": None,
+ "name": None,
+ "postal_code": None,
+ "address": None,
+ "email": None,
+ "birth": None,
+ "is_corporate": None,
+ "tax_category": None,
+ },
+ "balance": 20,
+ "exchange_balance": 21,
+ "exchange_commitment": 22,
+ "pending_transfer": 10,
+ "locked": 20,
+ "modified": "2023-10-24T02:20:00",
+ },
+ {
+ "account_address": _account_address_1,
+ "personal_information": {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "balance": 10,
+ "exchange_balance": 11,
+ "exchange_commitment": 12,
+ "pending_transfer": 5,
+ "locked": 10,
+ "modified": "2023-10-24T01:10:00",
+ },
+ ],
+ }
+
+ #
+ # Sort Item: holder_name
+ def test_normal_5_7(self, client, db):
+ user = config_eth_account("user1")
+ _issuer_address = user["address"]
+ _token_address = "0x82b1c9374aB625380bd498a3d9dF4033B8A0E3Bb"
+ _account_address_1 = "0xb75c7545b9230FEe99b7af370D38eBd3DAD929f7"
+ _account_address_2 = "0x3F198534Bbe3B2a197d3B317d41392F348EAC707"
+ _account_address_3 = "0x8277D905F37F8a9717F5718d0daC21495dFE74bf"
_account_address_4 = "0x917eFFaC072dcda308e2337636f562D0A96F42eA"
account = Account()
@@ -4336,7 +5204,7 @@ def test_normal_5_6(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -4580,9 +5448,9 @@ def test_normal_5_6(self, client, db):
],
}
- #
+ #
# Sort Item: key_manager
- def test_normal_5_7(self, client, db):
+ def test_normal_5_8(self, client, db):
user = config_eth_account("user1")
_issuer_address = user["address"]
_token_address = "0x82b1c9374aB625380bd498a3d9dF4033B8A0E3Bb"
@@ -4601,7 +5469,7 @@ def test_normal_5_7(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -4865,7 +5733,7 @@ def test_normal_6_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -5076,7 +5944,7 @@ def test_normal_6_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -5322,7 +6190,7 @@ def test_error_4(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_holders_count_GET.py b/tests/app/test_bond_tokens_{token_address}_holders_count_GET.py
similarity index 98%
rename from tests/test_app_routers_bond_tokens_{token_address}_holders_count_GET.py
rename to tests/app/test_bond_tokens_{token_address}_holders_count_GET.py
index a29a3a35..03699c35 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_holders_count_GET.py
+++ b/tests/app/test_bond_tokens_{token_address}_holders_count_GET.py
@@ -55,7 +55,7 @@ def test_normal_1_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -90,7 +90,7 @@ def test_normal_1_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
idx_position_1 = IDXPosition()
@@ -134,7 +134,7 @@ def test_normal_1_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
idx_position_1 = IDXPosition()
@@ -196,7 +196,7 @@ def test_normal_1_4(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
idx_position_1 = IDXPosition()
@@ -250,7 +250,7 @@ def test_normal_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
idx_position_1 = IDXPosition()
@@ -417,7 +417,7 @@ def test_error_4(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_holders_{account_address}_GET.py b/tests/app/test_bond_tokens_{token_address}_holders_{account_address}_GET.py
similarity index 98%
rename from tests/test_app_routers_bond_tokens_{token_address}_holders_{account_address}_GET.py
rename to tests/app/test_bond_tokens_{token_address}_holders_{account_address}_GET.py
index b062cc38..341e5fd3 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_holders_{account_address}_GET.py
+++ b/tests/app/test_bond_tokens_{token_address}_holders_{account_address}_GET.py
@@ -60,7 +60,7 @@ def test_normal_1_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: Personal Info
@@ -130,7 +130,7 @@ def test_normal_1_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: Position
@@ -211,7 +211,7 @@ def test_normal_1_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: Position
@@ -311,7 +311,7 @@ def test_normal_2_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
idx_position_1 = IDXPosition()
@@ -373,7 +373,7 @@ def test_normal_2_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
idx_position_1 = IDXPosition()
@@ -529,7 +529,7 @@ def test_error_4(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_personal_info_POST.py b/tests/app/test_bond_tokens_{token_address}_personal_info_POST.py
similarity index 99%
rename from tests/test_app_routers_bond_tokens_{token_address}_personal_info_POST.py
rename to tests/app/test_bond_tokens_{token_address}_personal_info_POST.py
index b671a987..f490e214 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_personal_info_POST.py
+++ b/tests/app/test_bond_tokens_{token_address}_personal_info_POST.py
@@ -59,7 +59,7 @@ def test_normal_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -140,7 +140,7 @@ def test_normal_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -227,7 +227,7 @@ def test_normal_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -680,7 +680,7 @@ def test_error_4(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -738,7 +738,7 @@ def test_error_5(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_personal_info_batch_GET.py b/tests/app/test_bond_tokens_{token_address}_personal_info_batch_GET.py
similarity index 97%
rename from tests/test_app_routers_bond_tokens_{token_address}_personal_info_batch_GET.py
rename to tests/app/test_bond_tokens_{token_address}_personal_info_batch_GET.py
index 9f918f2c..5da89c3e 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_personal_info_batch_GET.py
+++ b/tests/app/test_bond_tokens_{token_address}_personal_info_batch_GET.py
@@ -61,7 +61,7 @@ def test_normal_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -94,7 +94,7 @@ def test_normal_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# Prepare data : BatchRegisterPersonalInfoUpload
@@ -153,7 +153,7 @@ def test_normal_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# Prepare data : BatchRegisterPersonalInfoUpload
@@ -208,7 +208,7 @@ def test_normal_4(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# Prepare data : BatchRegisterPersonalInfoUpload
@@ -263,7 +263,7 @@ def test_normal_5(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# Prepare data : BatchRegisterPersonalInfoUpload
@@ -327,7 +327,7 @@ def test_error_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -370,7 +370,7 @@ def test_error_2(self, client, db):
token.issuer_address = _issuer_address_2
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# Prepare data : BatchRegisterPersonalInfoUpload
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_personal_info_batch_POST.py b/tests/app/test_bond_tokens_{token_address}_personal_info_batch_POST.py
similarity index 99%
rename from tests/test_app_routers_bond_tokens_{token_address}_personal_info_batch_POST.py
rename to tests/app/test_bond_tokens_{token_address}_personal_info_batch_POST.py
index 72dee6f2..f642c94d 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_personal_info_batch_POST.py
+++ b/tests/app/test_bond_tokens_{token_address}_personal_info_batch_POST.py
@@ -70,7 +70,7 @@ def test_normal_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -147,7 +147,7 @@ def test_normal_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -735,7 +735,7 @@ def test_error_4_1(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -797,7 +797,7 @@ def test_error_4_2(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 1
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_personal_info_batch_{batch_id}_GET.py b/tests/app/test_bond_tokens_{token_address}_personal_info_batch_{batch_id}_GET.py
similarity index 99%
rename from tests/test_app_routers_bond_tokens_{token_address}_personal_info_batch_{batch_id}_GET.py
rename to tests/app/test_bond_tokens_{token_address}_personal_info_batch_{batch_id}_GET.py
index 2e09c6d2..5321210c 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_personal_info_batch_{batch_id}_GET.py
+++ b/tests/app/test_bond_tokens_{token_address}_personal_info_batch_{batch_id}_GET.py
@@ -95,7 +95,7 @@ def test_normal_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# Prepare data : BatchRegisterPersonalInfoUpload
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_redeem_GET.py b/tests/app/test_bond_tokens_{token_address}_redeem_GET.py
similarity index 98%
rename from tests/test_app_routers_bond_tokens_{token_address}_redeem_GET.py
rename to tests/app/test_bond_tokens_{token_address}_redeem_GET.py
index 6a072af6..cf2b8c9f 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_redeem_GET.py
+++ b/tests/app/test_bond_tokens_{token_address}_redeem_GET.py
@@ -74,7 +74,7 @@ def test_normal_1(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXIssueRedeem
@@ -110,7 +110,7 @@ def test_normal_2(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXIssueRedeem
@@ -191,7 +191,7 @@ def test_normal_3(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXIssueRedeem
@@ -278,7 +278,7 @@ def test_normal_4(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXIssueRedeem
@@ -365,7 +365,7 @@ def test_error_2(self, client, db):
_token.token_address = self.test_token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -425,7 +425,7 @@ def test_error_4_1(self, client, db):
"detail": [
{
"ctx": {"expected": "0 or 1"},
- "input": -1,
+ "input": "-1",
"loc": ["query", "sort_order"],
"msg": "Input should be 0 or 1",
"type": "enum",
@@ -449,7 +449,7 @@ def test_error_4_2(self, client, db):
"detail": [
{
"ctx": {"expected": "0 or 1"},
- "input": 2,
+ "input": "2",
"loc": ["query", "sort_order"],
"msg": "Input should be 0 or 1",
"type": "enum",
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_redeem_POST.py b/tests/app/test_bond_tokens_{token_address}_redeem_POST.py
similarity index 98%
rename from tests/test_app_routers_bond_tokens_{token_address}_redeem_POST.py
rename to tests/app/test_bond_tokens_{token_address}_redeem_POST.py
index 9b801f74..5c71938b 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_redeem_POST.py
+++ b/tests/app/test_bond_tokens_{token_address}_redeem_POST.py
@@ -58,7 +58,7 @@ def test_normal_1(self, IbetStraightBondContract_mock, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -113,7 +113,7 @@ def test_normal_2(self, IbetStraightBondContract_mock, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -159,7 +159,7 @@ def test_error_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -206,7 +206,7 @@ def test_error_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -253,7 +253,7 @@ def test_error_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -396,7 +396,7 @@ def test_error_7(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -510,7 +510,7 @@ def test_error_10(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -558,7 +558,7 @@ def test_error_11(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_redeem_batch_GET.py b/tests/app/test_bond_tokens_{token_address}_redeem_batch_GET.py
similarity index 98%
rename from tests/test_app_routers_bond_tokens_{token_address}_redeem_batch_GET.py
rename to tests/app/test_bond_tokens_{token_address}_redeem_batch_GET.py
index f5a55b8b..347dd656 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_redeem_batch_GET.py
+++ b/tests/app/test_bond_tokens_{token_address}_redeem_batch_GET.py
@@ -52,7 +52,7 @@ def test_normal_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -80,7 +80,7 @@ def test_normal_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
redeem_upload1 = BatchIssueRedeemUpload()
@@ -127,7 +127,7 @@ def test_normal_3_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
redeem_upload1 = BatchIssueRedeemUpload()
@@ -234,7 +234,7 @@ def test_normal_3_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
redeem_upload1 = BatchIssueRedeemUpload()
@@ -328,7 +328,7 @@ def test_normal_3_3(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
redeem_upload1 = BatchIssueRedeemUpload()
@@ -428,7 +428,7 @@ def test_normal_4(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
redeem_upload1 = BatchIssueRedeemUpload()
@@ -520,7 +520,7 @@ def test_normal_5(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
additional_issue_upload1 = BatchIssueRedeemUpload()
@@ -643,7 +643,7 @@ def test_error_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_redeem_batch_POST.py b/tests/app/test_bond_tokens_{token_address}_redeem_batch_POST.py
similarity index 97%
rename from tests/test_app_routers_bond_tokens_{token_address}_redeem_batch_POST.py
rename to tests/app/test_bond_tokens_{token_address}_redeem_batch_POST.py
index 4d10199d..57a84673 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_redeem_batch_POST.py
+++ b/tests/app/test_bond_tokens_{token_address}_redeem_batch_POST.py
@@ -66,7 +66,7 @@ def test_normal_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -131,7 +131,7 @@ def test_normal_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -206,7 +206,7 @@ def test_error_1_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -258,7 +258,7 @@ def test_error_1_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -313,7 +313,7 @@ def test_error_1_3_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -368,7 +368,7 @@ def test_error_1_3_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -423,7 +423,7 @@ def test_error_1_4(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -472,7 +472,7 @@ def test_error_1_5(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -521,7 +521,7 @@ def test_error_1_6(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -568,7 +568,7 @@ def test_error_1_7_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -615,7 +615,7 @@ def test_error_1_7_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -703,7 +703,7 @@ def test_error_1_8_2(self, client, db):
token.token_address = token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_redeem_batch_{batch_id}_GET.py b/tests/app/test_bond_tokens_{token_address}_redeem_batch_{batch_id}_GET.py
similarity index 98%
rename from tests/test_app_routers_bond_tokens_{token_address}_redeem_batch_{batch_id}_GET.py
rename to tests/app/test_bond_tokens_{token_address}_redeem_batch_{batch_id}_GET.py
index e23f181a..5a0f2b72 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_redeem_batch_{batch_id}_GET.py
+++ b/tests/app/test_bond_tokens_{token_address}_redeem_batch_{batch_id}_GET.py
@@ -71,7 +71,7 @@ def test_normal_1_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = test_token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
batch_upload = BatchIssueRedeemUpload()
@@ -158,7 +158,7 @@ def test_normal_1_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = test_token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
batch_upload = BatchIssueRedeemUpload()
@@ -245,7 +245,7 @@ def test_normal_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = test_token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
batch_upload = BatchIssueRedeemUpload()
@@ -358,7 +358,7 @@ def test_error_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = test_token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
batch_upload = BatchIssueRedeemUpload()
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_scheduled_events_GET.py b/tests/app/test_bond_tokens_{token_address}_scheduled_events_GET.py
similarity index 93%
rename from tests/test_app_routers_bond_tokens_{token_address}_scheduled_events_GET.py
rename to tests/app/test_bond_tokens_{token_address}_scheduled_events_GET.py
index 474b8d6d..0aa2e2c1 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_scheduled_events_GET.py
+++ b/tests/app/test_bond_tokens_{token_address}_scheduled_events_GET.py
@@ -18,9 +18,9 @@
"""
import uuid
-from datetime import datetime, timedelta
+from datetime import UTC, datetime, timedelta
-from pytz import timezone
+import pytz
from app.model.db import ScheduledEvents, ScheduledEventType, TokenType
from config import TZ
@@ -30,7 +30,7 @@
class TestAppRoutersBondTokensTokenAddressScheduledEventsGET:
# target API endpoint
base_url = "/bond/tokens/{}/scheduled_events"
- local_tz = timezone(TZ)
+ local_tz = pytz.timezone(TZ)
###########################################################################
# Normal Case
@@ -45,9 +45,9 @@ def test_normal_1(self, client, db):
_token_address = "token_address_test"
# prepare data
- datetime_now_utc = datetime.utcnow()
+ datetime_now_utc = datetime.now(UTC).replace(tzinfo=None)
datetime_now_str = (
- timezone("UTC")
+ pytz.timezone("UTC")
.localize(datetime_now_utc)
.astimezone(self.local_tz)
.isoformat()
@@ -117,9 +117,9 @@ def test_normal_2(self, client, db):
# prepare data
datetime_list = []
- datetime_utc = datetime.utcnow() + timedelta(hours=1)
+ datetime_utc = datetime.now(UTC).replace(tzinfo=None) + timedelta(hours=1)
datetime_list.append(datetime_utc)
- datetime_utc = datetime.utcnow()
+ datetime_utc = datetime.now(UTC).replace(tzinfo=None)
datetime_list.append(datetime_utc.replace(tzinfo=None))
uuid_list = [str(uuid.uuid4()), str(uuid.uuid4())]
@@ -167,14 +167,14 @@ def test_normal_2(self, client, db):
"scheduled_event_id": uuid_list[0],
"token_address": _token_address,
"token_type": TokenType.IBET_STRAIGHT_BOND.value,
- "scheduled_datetime": timezone("UTC")
+ "scheduled_datetime": pytz.timezone("UTC")
.localize(datetime_list[0])
.astimezone(self.local_tz)
.isoformat(),
"event_type": ScheduledEventType.UPDATE.value,
"status": 0,
"data": update_data,
- "created": timezone("UTC")
+ "created": pytz.timezone("UTC")
.localize(datetime_list[0])
.astimezone(self.local_tz)
.isoformat(),
@@ -183,14 +183,14 @@ def test_normal_2(self, client, db):
"scheduled_event_id": uuid_list[1],
"token_address": _token_address,
"token_type": TokenType.IBET_STRAIGHT_BOND.value,
- "scheduled_datetime": timezone("UTC")
+ "scheduled_datetime": pytz.timezone("UTC")
.localize(datetime_list[1])
.astimezone(self.local_tz)
.isoformat(),
"event_type": ScheduledEventType.UPDATE.value,
"status": 0,
"data": update_data,
- "created": timezone("UTC")
+ "created": pytz.timezone("UTC")
.localize(datetime_list[1])
.astimezone(self.local_tz)
.isoformat(),
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_scheduled_events_POST.py b/tests/app/test_bond_tokens_{token_address}_scheduled_events_POST.py
similarity index 81%
rename from tests/test_app_routers_bond_tokens_{token_address}_scheduled_events_POST.py
rename to tests/app/test_bond_tokens_{token_address}_scheduled_events_POST.py
index d2dcbaf8..6ea29a5e 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_scheduled_events_POST.py
+++ b/tests/app/test_bond_tokens_{token_address}_scheduled_events_POST.py
@@ -17,7 +17,7 @@
SPDX-License-Identifier: Apache-2.0
"""
-from datetime import datetime, timezone
+from datetime import UTC, datetime
from pytz import timezone as tz
from sqlalchemy import and_, select
@@ -63,13 +63,13 @@ def test_normal_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
# test data
- datetime_now_utc = datetime.now(timezone.utc) # utc
+ datetime_now_utc = datetime.now(UTC) # utc
datetime_now_str = datetime_now_utc.isoformat()
update_data = {
"face_value": 10000,
@@ -86,6 +86,7 @@ def test_normal_1(self, client, db):
"is_redeemed": True,
"tradable_exchange_contract_address": "0xe883A6f441Ad5682d37DF31d34fc012bcB07A740",
"personal_info_contract_address": "0xa4CEe3b909751204AA151860ebBE8E7A851c2A1a",
+ "require_personal_info_registered": False,
"contact_information": "問い合わせ先test",
"privacy_policy": "プライバシーポリシーtest",
"transfer_approval_required": True,
@@ -149,7 +150,7 @@ def test_normal_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -172,6 +173,7 @@ def test_normal_2(self, client, db):
"is_redeemed": True,
"tradable_exchange_contract_address": "0xe883A6f441Ad5682d37DF31d34fc012bcB07A740",
"personal_info_contract_address": "0xa4CEe3b909751204AA151860ebBE8E7A851c2A1a",
+ "require_personal_info_registered": False,
"contact_information": "問い合わせ先test",
"privacy_policy": "プライバシーポリシーtest",
"transfer_approval_required": True,
@@ -208,7 +210,7 @@ def test_normal_2(self, client, db):
assert resp_1.json() == {"scheduled_event_id": _scheduled_event.event_id}
assert _scheduled_event.token_type == TokenType.IBET_STRAIGHT_BOND.value
assert _scheduled_event.scheduled_datetime == datetime_now_jst.astimezone(
- timezone.utc
+ UTC
).replace(tzinfo=None)
assert _scheduled_event.event_type == ScheduledEventType.UPDATE.value
assert _scheduled_event.status == 0
@@ -226,7 +228,7 @@ def test_error_1_1(self, client, db):
_token_address = "token_address_test"
# test data
- datetime_now_utc = datetime.now(timezone.utc)
+ datetime_now_utc = datetime.now(UTC)
datetime_now_str = datetime_now_utc.isoformat()
update_data = {}
@@ -271,7 +273,7 @@ def test_error_1_2(self, client, db):
_token_address = "token_address_test"
# test data
- datetime_now_utc = datetime.now(timezone.utc)
+ datetime_now_utc = datetime.now(UTC)
datetime_now_str = datetime_now_utc.isoformat()
update_data = {"is_redeemed": False}
@@ -312,7 +314,7 @@ def test_error_2(self, client, db):
_token_address = "token_address_test"
# test data
- datetime_now_utc = datetime.now(timezone.utc)
+ datetime_now_utc = datetime.now(UTC)
datetime_now_str = datetime_now_utc.isoformat()
update_data = {
"face_value": 10000,
@@ -360,13 +362,13 @@ def test_error_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
# test data
- datetime_now_utc = datetime.now(timezone.utc)
+ datetime_now_utc = datetime.now(UTC)
datetime_now_str = datetime_now_utc.isoformat()
update_data = {}
@@ -409,7 +411,7 @@ def test_error_4(self, client, db):
db.commit()
# test data
- datetime_now_utc = datetime.now(timezone.utc)
+ datetime_now_utc = datetime.now(UTC)
datetime_now_str = datetime_now_utc.isoformat()
update_data = {}
@@ -506,13 +508,13 @@ def test_error_6(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
# test data
- datetime_now_utc = datetime.now(timezone.utc) # utc
+ datetime_now_utc = datetime.now(UTC) # utc
datetime_now_str = datetime_now_utc.isoformat()
update_data = {
"face_value": 10000,
@@ -525,6 +527,7 @@ def test_error_6(self, client, db):
"is_redeemed": True,
"tradable_exchange_contract_address": "0xe883A6f441Ad5682d37DF31d34fc012bcB07A740",
"personal_info_contract_address": "0xa4CEe3b909751204AA151860ebBE8E7A851c2A1a",
+ "require_personal_info_registered": False,
"contact_information": "問い合わせ先test",
"privacy_policy": "プライバシーポリシーtest",
"memo": "memo_test1",
@@ -551,3 +554,115 @@ def test_error_6(self, client, db):
"meta": {"code": 1, "title": "InvalidParameterError"},
"detail": "this token is temporarily unavailable",
}
+
+ #
+ # OperationNotSupportedVersionError: v23.12
+ def test_error_7_1(self, client, db):
+ test_account = config_eth_account("user1")
+ _issuer_address = test_account["address"]
+ _keyfile = test_account["keyfile_json"]
+ _token_address = "token_address_test"
+
+ # prepare data
+ account = Account()
+ account.issuer_address = _issuer_address
+ account.keyfile = _keyfile
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.tx_hash = ""
+ token.issuer_address = _issuer_address
+ token.token_address = _token_address
+ token.abi = ""
+ token.token_status = 1
+ token.version = TokenVersion.V_22_12
+ db.add(token)
+
+ db.commit()
+
+ # test data
+ datetime_now_utc = datetime.now(UTC)
+ datetime_now_str = datetime_now_utc.isoformat()
+ update_data = {
+ "base_fx_rate": 10.0,
+ }
+
+ # request target API
+ req_param = {
+ "scheduled_datetime": datetime_now_str,
+ "event_type": "Update",
+ "data": update_data,
+ }
+ resp = client.post(
+ self.base_url.format(_token_address),
+ json=req_param,
+ headers={
+ "issuer-address": _issuer_address,
+ "eoa-password": E2EEUtils.encrypt("password"),
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 400
+ assert resp.json() == {
+ "meta": {"code": 6, "title": "OperationNotSupportedVersionError"},
+ "detail": "the operation is not supported in 22_12",
+ }
+
+ #
+ # OperationNotSupportedVersionError: v24.6
+ def test_error_7_2(self, client, db):
+ test_account = config_eth_account("user1")
+ _issuer_address = test_account["address"]
+ _keyfile = test_account["keyfile_json"]
+ _token_address = "token_address_test"
+
+ # prepare data
+ account = Account()
+ account.issuer_address = _issuer_address
+ account.keyfile = _keyfile
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.tx_hash = ""
+ token.issuer_address = _issuer_address
+ token.token_address = _token_address
+ token.abi = ""
+ token.token_status = 1
+ token.version = TokenVersion.V_23_12
+ db.add(token)
+
+ db.commit()
+
+ # test data
+ datetime_now_utc = datetime.now(UTC)
+ datetime_now_str = datetime_now_utc.isoformat()
+ update_data = {
+ "require_personal_info_registered": False,
+ }
+
+ # request target API
+ req_param = {
+ "scheduled_datetime": datetime_now_str,
+ "event_type": "Update",
+ "data": update_data,
+ }
+ resp = client.post(
+ self.base_url.format(_token_address),
+ json=req_param,
+ headers={
+ "issuer-address": _issuer_address,
+ "eoa-password": E2EEUtils.encrypt("password"),
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 400
+ assert resp.json() == {
+ "meta": {"code": 6, "title": "OperationNotSupportedVersionError"},
+ "detail": "the operation is not supported in 23_12",
+ }
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_scheduled_events_{scheduled_event_id}_DELETE.py b/tests/app/test_bond_tokens_{token_address}_scheduled_events_{scheduled_event_id}_DELETE.py
similarity index 97%
rename from tests/test_app_routers_bond_tokens_{token_address}_scheduled_events_{scheduled_event_id}_DELETE.py
rename to tests/app/test_bond_tokens_{token_address}_scheduled_events_{scheduled_event_id}_DELETE.py
index c0d757ba..96fbe341 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_scheduled_events_{scheduled_event_id}_DELETE.py
+++ b/tests/app/test_bond_tokens_{token_address}_scheduled_events_{scheduled_event_id}_DELETE.py
@@ -18,9 +18,9 @@
"""
import uuid
-from datetime import datetime
+from datetime import UTC, datetime
-from pytz import timezone
+import pytz
from sqlalchemy import select
from app.model.db import Account, ScheduledEvents, ScheduledEventType, TokenType
@@ -32,7 +32,7 @@
class TestAppRoutersBondTokensTokenAddressScheduledEventsScheduledEventIdDELETE:
# target API endpoint
base_url = "/bond/tokens/{}/scheduled_events/{}"
- local_tz = timezone(TZ)
+ local_tz = pytz.timezone(TZ)
###########################################################################
# Normal Case
@@ -54,9 +54,9 @@ def test_normal_1(self, client, db):
db.commit()
- datetime_now_utc = datetime.utcnow()
+ datetime_now_utc = datetime.now(UTC).replace(tzinfo=None)
datetime_now_str = (
- timezone("UTC")
+ pytz.timezone("UTC")
.localize(datetime_now_utc)
.astimezone(self.local_tz)
.isoformat()
diff --git a/tests/test_app_routers_bond_tokens_{token_address}_scheduled_events_{scheduled_event_id}_GET.py b/tests/app/test_bond_tokens_{token_address}_scheduled_events_{scheduled_event_id}_GET.py
similarity index 95%
rename from tests/test_app_routers_bond_tokens_{token_address}_scheduled_events_{scheduled_event_id}_GET.py
rename to tests/app/test_bond_tokens_{token_address}_scheduled_events_{scheduled_event_id}_GET.py
index 419b0a9e..c82eb281 100644
--- a/tests/test_app_routers_bond_tokens_{token_address}_scheduled_events_{scheduled_event_id}_GET.py
+++ b/tests/app/test_bond_tokens_{token_address}_scheduled_events_{scheduled_event_id}_GET.py
@@ -18,9 +18,9 @@
"""
import uuid
-from datetime import datetime
+from datetime import UTC, datetime
-from pytz import timezone
+import pytz
from app.model.db import ScheduledEvents, ScheduledEventType, TokenType
from config import TZ
@@ -30,7 +30,7 @@
class TestAppRoutersBondTokensTokenAddressScheduledEventsScheduledEventIdGET:
# target API endpoint
base_url = "/bond/tokens/{}/scheduled_events/{}"
- local_tz = timezone(TZ)
+ local_tz = pytz.timezone(TZ)
###########################################################################
# Normal Case
@@ -45,9 +45,9 @@ def test_normal_1(self, client, db):
_token_address = "token_address_test"
# prepare data
- datetime_now_utc = datetime.utcnow()
+ datetime_now_utc = datetime.now(UTC).replace(tzinfo=None)
datetime_now_str = (
- timezone("UTC")
+ pytz.timezone("UTC")
.localize(datetime_now_utc)
.astimezone(self.local_tz)
.isoformat()
@@ -113,9 +113,9 @@ def test_normal_2(self, client, db):
_token_address = "token_address_test"
# prepare data
- datetime_now_utc = datetime.utcnow()
+ datetime_now_utc = datetime.now(UTC).replace(tzinfo=None)
datetime_now_str = (
- timezone("UTC")
+ pytz.timezone("UTC")
.localize(datetime_now_utc)
.astimezone(self.local_tz)
.isoformat()
diff --git a/tests/test_app_routers_bond_transfer_approvals_GET.py b/tests/app/test_bond_transfer_approvals_GET.py
similarity index 98%
rename from tests/test_app_routers_bond_transfer_approvals_GET.py
rename to tests/app/test_bond_transfer_approvals_GET.py
index 79538449..b04ece78 100644
--- a/tests/test_app_routers_bond_transfer_approvals_GET.py
+++ b/tests/app/test_bond_transfer_approvals_GET.py
@@ -100,7 +100,7 @@ def test_normal_1(self, client, db):
_token.token_address = self.test_token_address_1
_token.abi = {}
_token.token_status = 2
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Token(share)
@@ -110,7 +110,7 @@ def test_normal_1(self, client, db):
_token.issuer_address = self.test_issuer_address_1
_token.token_address = self.test_token_address_2
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval(failed token)
@@ -207,7 +207,7 @@ def test_normal_2(self, client, db):
_token.issuer_address = self.test_issuer_address_1
_token.token_address = self.test_token_address_1
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval(ApplyFor(unapproved))
@@ -392,7 +392,7 @@ def test_normal_3_1(self, client, db):
_token.issuer_address = self.test_issuer_address_1
_token.token_address = self.test_token_address_1
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Token(issuer-1)
@@ -402,7 +402,7 @@ def test_normal_3_1(self, client, db):
_token.issuer_address = self.test_issuer_address_1
_token.token_address = self.test_token_address_2
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Token(issuer-2)
@@ -412,7 +412,7 @@ def test_normal_3_1(self, client, db):
_token.issuer_address = self.test_issuer_address_2
_token.token_address = self.test_token_address_3
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval(issuer-1 token-1)
@@ -579,7 +579,7 @@ def test_normal_3_2(self, client, db):
_token.issuer_address = self.test_issuer_address_1
_token.token_address = self.test_token_address_1
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Token(issuer-1)
@@ -589,7 +589,7 @@ def test_normal_3_2(self, client, db):
_token.issuer_address = self.test_issuer_address_1
_token.token_address = self.test_token_address_2
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Token(issuer-2)
@@ -599,7 +599,7 @@ def test_normal_3_2(self, client, db):
_token.issuer_address = self.test_issuer_address_2
_token.token_address = self.test_token_address_3
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval(issuer-1 token-1)
@@ -774,7 +774,7 @@ def test_normal_4(self, client, db):
_token.issuer_address = self.test_issuer_address_1
_token.token_address = self.test_token_address_1
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Token(issuer-1)
@@ -784,7 +784,7 @@ def test_normal_4(self, client, db):
_token.issuer_address = self.test_issuer_address_1
_token.token_address = self.test_token_address_2
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Token(issuer-1)
@@ -794,7 +794,7 @@ def test_normal_4(self, client, db):
_token.issuer_address = self.test_issuer_address_1
_token.token_address = self.test_token_address_3
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Token(issuer-1)
@@ -804,7 +804,7 @@ def test_normal_4(self, client, db):
_token.issuer_address = self.test_issuer_address_1
_token.token_address = self.test_token_address_4
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval(issuer-1 token-1)
diff --git a/tests/test_app_routers_bond_transfer_approvals_{token_address}_GET.py b/tests/app/test_bond_transfer_approvals_{token_address}_GET.py
similarity index 99%
rename from tests/test_app_routers_bond_transfer_approvals_{token_address}_GET.py
rename to tests/app/test_bond_transfer_approvals_{token_address}_GET.py
index f84689cf..9774fcb7 100644
--- a/tests/test_app_routers_bond_transfer_approvals_{token_address}_GET.py
+++ b/tests/app/test_bond_transfer_approvals_{token_address}_GET.py
@@ -110,7 +110,7 @@ def test_normal_1_1(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -136,7 +136,7 @@ def test_normal_1_2(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -330,7 +330,7 @@ def test_normal_2(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -450,7 +450,7 @@ def test_normal_3(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -654,7 +654,7 @@ def test_normal_4_1(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -767,7 +767,7 @@ def test_normal_4_2(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -881,7 +881,7 @@ def test_normal_4_3_1(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -1027,7 +1027,7 @@ def test_normal_4_3_2(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -1173,7 +1173,7 @@ def test_normal_4_3_3(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval
@@ -1407,7 +1407,7 @@ def test_normal_4_3_4(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -1627,7 +1627,7 @@ def test_normal_4_3_5(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -1879,7 +1879,7 @@ def test_normal_5_1(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -2079,7 +2079,7 @@ def test_normal_5_2(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -2319,7 +2319,7 @@ def test_normal_5_3(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -2559,7 +2559,7 @@ def test_normal_5_4(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -2764,7 +2764,7 @@ def test_normal_5_5(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -2967,7 +2967,7 @@ def test_normal_5_6(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -3206,7 +3206,7 @@ def test_normal_5_7(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -3452,7 +3452,7 @@ def test_normal_5_8(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -3694,7 +3694,7 @@ def test_normal_5_9(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -4132,25 +4132,23 @@ def test_error_1_1(self, client, db):
"meta": {"code": 1, "title": "RequestValidationError"},
"detail": [
{
- "input": "a",
+ "type": "enum",
"loc": ["query", "status", 0],
- "msg": "Input should be a valid integer, unable to parse string "
- "as an integer",
- "type": "int_parsing",
+ "msg": "Input should be 0, 1, 2 or 3",
+ "input": "a",
+ "ctx": {"expected": "0, 1, 2 or 3"},
},
{
- "input": "c",
- "loc": ["query", "offset"],
- "msg": "Input should be a valid integer, unable to parse string "
- "as an integer",
"type": "int_parsing",
+ "loc": ["query", "offset"],
+ "msg": "Input should be a valid integer, unable to parse string as an integer",
+ "input": "c",
},
{
- "input": "d",
- "loc": ["query", "limit"],
- "msg": "Input should be a valid integer, unable to parse string "
- "as an integer",
"type": "int_parsing",
+ "loc": ["query", "limit"],
+ "msg": "Input should be a valid integer, unable to parse string as an integer",
+ "input": "d",
},
],
}
@@ -4175,7 +4173,7 @@ def test_error_1_2(self, client, db):
"detail": [
{
"ctx": {"expected": "0, 1, 2 or 3"},
- "input": -1,
+ "input": "-1",
"loc": ["query", "status", 0],
"msg": "Input should be 0, 1, 2 or 3",
"type": "enum",
@@ -4203,7 +4201,7 @@ def test_error_1_3(self, client, db):
"detail": [
{
"ctx": {"expected": "0, 1, 2 or 3"},
- "input": 4,
+ "input": "4",
"loc": ["query", "status", 0],
"msg": "Input should be 0, 1, 2 or 3",
"type": "enum",
@@ -4237,7 +4235,7 @@ def test_error_2(self, client, db):
_token.token_address = self.test_token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
diff --git a/tests/test_app_routers_bond_transfer_approvals_{token_address}_{id}_GET.py b/tests/app/test_bond_transfer_approvals_{token_address}_{id}_GET.py
similarity index 98%
rename from tests/test_app_routers_bond_transfer_approvals_{token_address}_{id}_GET.py
rename to tests/app/test_bond_transfer_approvals_{token_address}_{id}_GET.py
index afd0da70..71fd6fbe 100644
--- a/tests/test_app_routers_bond_transfer_approvals_{token_address}_{id}_GET.py
+++ b/tests/app/test_bond_transfer_approvals_{token_address}_{id}_GET.py
@@ -96,7 +96,7 @@ def test_normal_1_1(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -209,7 +209,7 @@ def test_normal_1_2(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval
@@ -274,7 +274,7 @@ def test_normal_2_1(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval
@@ -384,7 +384,7 @@ def test_normal_2_2(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval
@@ -496,7 +496,7 @@ def test_normal_3(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -610,7 +610,7 @@ def test_normal_4_1(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval
@@ -722,7 +722,7 @@ def test_normal_4_2(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval
@@ -835,7 +835,7 @@ def test_normal_4_3(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -982,7 +982,7 @@ def test_error_2(self, client, db):
_token.token_address = self.test_token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -1010,7 +1010,7 @@ def test_error_3(self, client, db):
_token.token_address = self.test_token_address
_token.abi = {}
_token.token_status = 1
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
diff --git a/tests/test_app_routers_bond_transfer_approvals_{token_address}_{id}_POST.py b/tests/app/test_bond_transfer_approvals_{token_address}_{id}_POST.py
similarity index 97%
rename from tests/test_app_routers_bond_transfer_approvals_{token_address}_{id}_POST.py
rename to tests/app/test_bond_transfer_approvals_{token_address}_{id}_POST.py
index 7638f467..5e5ed817 100644
--- a/tests/test_app_routers_bond_transfer_approvals_{token_address}_{id}_POST.py
+++ b/tests/app/test_bond_transfer_approvals_{token_address}_{id}_POST.py
@@ -18,12 +18,11 @@
"""
import hashlib
-from datetime import datetime
+from datetime import UTC, datetime
from unittest import mock
from unittest.mock import ANY, MagicMock
import pytest
-from pytz import timezone
from sqlalchemy import select
import config
@@ -49,8 +48,6 @@
from app.utils.e2ee_utils import E2EEUtils
from tests.account_config import config_eth_account
-local_tz = timezone(config.TZ)
-
class TestAppRoutersBondTransferApprovalsTokenAddressIdPOST:
# target API endpoint
@@ -93,7 +90,7 @@ def test_normal_1_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -168,7 +165,10 @@ def test_normal_1_1(self, client, db):
assert resp.status_code == 200
assert resp.json() is None
- _expected = {"application_id": 100, "data": str(datetime.utcnow().timestamp())}
+ _expected = {
+ "application_id": 100,
+ "data": str(datetime.now(UTC).replace(tzinfo=None).timestamp()),
+ }
mock_transfer.assert_called_once_with(
data=ApproveTransferParams(**_expected),
@@ -227,7 +227,7 @@ def test_normal_1_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -303,7 +303,10 @@ def test_normal_1_2(self, client, db):
assert resp.status_code == 200
assert resp.json() is None
- _expected = {"escrow_id": 100, "data": str(datetime.utcnow().timestamp())}
+ _expected = {
+ "escrow_id": 100,
+ "data": str(datetime.now(UTC).replace(tzinfo=None).timestamp()),
+ }
mock_transfer.assert_called_once_with(
data=EscrowApproveTransferParams(**_expected),
@@ -362,7 +365,7 @@ def test_normal_2_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -437,7 +440,10 @@ def test_normal_2_1(self, client, db):
assert resp.status_code == 200
assert resp.json() is None
- _expected = {"application_id": 100, "data": str(datetime.utcnow().timestamp())}
+ _expected = {
+ "application_id": 100,
+ "data": str(datetime.now(UTC).replace(tzinfo=None).timestamp()),
+ }
mock_transfer.assert_called_once_with(
data=CancelTransferParams(**_expected),
@@ -501,7 +507,7 @@ def test_normal_3(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -576,7 +582,10 @@ def test_normal_3(self, client, db):
assert resp.status_code == 200
assert resp.json() is None
- _expected = {"application_id": 100, "data": str(datetime.utcnow().timestamp())}
+ _expected = {
+ "application_id": 100,
+ "data": str(datetime.now(UTC).replace(tzinfo=None).timestamp()),
+ }
mock_transfer.assert_called_once_with(
data=ApproveTransferParams(**_expected),
@@ -832,7 +841,7 @@ def test_error_3_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -877,7 +886,7 @@ def test_error_4_1(self, client, db):
_token.token_address = self.test_token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -921,7 +930,7 @@ def test_error_4_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -986,7 +995,7 @@ def test_error_4_3(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1051,7 +1060,7 @@ def test_error_4_4(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1114,7 +1123,7 @@ def test_error_4_5(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1177,7 +1186,7 @@ def test_error_4_6(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1253,7 +1262,7 @@ def test_error_5_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1346,7 +1355,7 @@ def test_error_5_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1456,7 +1465,7 @@ def test_error_5_3(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1550,7 +1559,7 @@ def test_error_5_4(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1655,7 +1664,7 @@ def test_error_6_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1748,7 +1757,7 @@ def test_error_6_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1846,7 +1855,7 @@ def test_error_7_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1914,7 +1923,7 @@ def test_error_7_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
diff --git a/tests/test_app_routers_bond_transfers_POST.py b/tests/app/test_bond_transfers_POST.py
similarity index 99%
rename from tests/test_app_routers_bond_transfers_POST.py
rename to tests/app/test_bond_transfers_POST.py
index de4bbdb8..dd9e02cd 100644
--- a/tests/test_app_routers_bond_transfers_POST.py
+++ b/tests/app/test_bond_transfers_POST.py
@@ -65,7 +65,7 @@ def test_normal_1(self, IbetStraightBondContract_mock, client, db):
token.issuer_address = _admin_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -140,7 +140,7 @@ def test_normal_2(self, IbetStraightBondContract_mock, client, db):
token.issuer_address = _admin_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -533,7 +533,7 @@ def test_error_9(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -593,7 +593,7 @@ def test_error_10(self, client, db):
token.issuer_address = _admin_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/app/test_bond_transfers_{token_address}_GET.py b/tests/app/test_bond_transfers_{token_address}_GET.py
new file mode 100644
index 00000000..0a414b4d
--- /dev/null
+++ b/tests/app/test_bond_transfers_{token_address}_GET.py
@@ -0,0 +1,1950 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+from datetime import datetime
+
+from pytz import timezone
+
+import config
+from app.model.db import (
+ IDXPersonalInfo,
+ IDXTransfer,
+ IDXTransferSourceEventType,
+ Token,
+ TokenType,
+ TokenVersion,
+)
+
+local_tz = timezone(config.TZ)
+
+
+class TestAppRoutersBondTransfersGET:
+ # target API endpoint
+ base_url = "/bond/transfers/{}"
+
+ test_transaction_hash = "test_transaction_hash"
+ test_issuer_address = "test_issuer_address"
+ test_token_address = "test_token_address"
+
+ test_from_address_1 = "test_from_address_1"
+ test_from_address_2 = "test_from_address_2"
+ test_to_address_1 = "test_to_address_1"
+ test_to_address_2 = "test_to_address_2"
+
+ test_block_timestamp = [
+ datetime.strptime("2022/01/02 15:20:30", "%Y/%m/%d %H:%M:%S"), # JST 2022/01/03
+ datetime.strptime("2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"), # JST 2022/01/02
+ datetime.strptime("2022/01/02 00:20:30", "%Y/%m/%d %H:%M:%S"), # JST 2022/01/02
+ ]
+ test_block_timestamp_str = [
+ "2022-01-03T00:20:30+09:00",
+ "2022-01-02T00:20:30+09:00",
+ "2022-01-02T09:20:30+09:00",
+ ]
+
+ ###########################################################################
+ # Normal Case
+ ###########################################################################
+
+ #
+ # default sort
+ def test_normal_1(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ for i in range(0, 3):
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = i
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[i]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(self.base_url.format(self.test_token_address))
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 3, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 0,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 1,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # offset, limit
+ def test_normal_2(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXPersonalInfo
+ _personal_info_from = IDXPersonalInfo()
+ _personal_info_from.account_address = self.test_from_address_1
+ _personal_info_from.issuer_address = self.test_issuer_address
+ _personal_info_from._personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ } # latest data
+ db.add(_personal_info_from)
+
+ _personal_info_to = IDXPersonalInfo()
+ _personal_info_to.account_address = self.test_to_address_1
+ _personal_info_to.issuer_address = self.test_issuer_address
+ _personal_info_to._personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ } # latest data
+ db.add(_personal_info_to)
+
+ # prepare data: IDXTransfer
+ for i in range(0, 3):
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = i
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[i]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address) + "?offset=1&limit=1"
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 3, "offset": 1, "limit": 1, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": {
+ "address": "address_test1",
+ "birth": "birth_test1",
+ "email": "email_test1",
+ "is_corporate": False,
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "tax_category": 10,
+ },
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": {
+ "address": "address_test2",
+ "birth": "birth_test2",
+ "email": "email_test2",
+ "is_corporate": False,
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "tax_category": 10,
+ },
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: block_timestamp_from
+ def test_normal_3_1(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 2
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"block_timestamp_from": "2022-01-02T09:20:30"},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 2, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 0,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: block_timestamp_to
+ def test_normal_3_2(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 2
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"block_timestamp_to": "2022-01-02T09:20:30"},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 2, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 1,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: from_address
+ def test_normal_3_3(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_2
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_2
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 2
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"from_address": self.test_from_address_1},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 1, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: to_address
+ def test_normal_3_4(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_2
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_2
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 2
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"to_address": self.test_to_address_1},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 1, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: from_address_name
+ def test_normal_3_5(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_2
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ # prepare data: IDXPersonalInfo
+ _personal_info_from = IDXPersonalInfo()
+ _personal_info_from.account_address = self.test_from_address_1
+ _personal_info_from.issuer_address = self.test_issuer_address
+ _personal_info_from._personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "テスト太郎1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ } # latest data
+ db.add(_personal_info_from)
+
+ _personal_info_to = IDXPersonalInfo()
+ _personal_info_to.account_address = self.test_from_address_2
+ _personal_info_to.issuer_address = self.test_issuer_address
+ _personal_info_to._personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ } # latest data
+ db.add(_personal_info_to)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"from_address_name": "テスト太郎1"}, # test_from_address_1's name
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 1, "offset": None, "limit": None, "total": 2},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": {
+ "key_manager": "key_manager_test1",
+ "name": "テスト太郎1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 0,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: to_address_name
+ def test_normal_3_6(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_2
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ # prepare data: IDXPersonalInfo
+ _personal_info_from = IDXPersonalInfo()
+ _personal_info_from.account_address = self.test_to_address_1
+ _personal_info_from.issuer_address = self.test_issuer_address
+ _personal_info_from._personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "テスト太郎1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ } # latest data
+ db.add(_personal_info_from)
+
+ _personal_info_to = IDXPersonalInfo()
+ _personal_info_to.account_address = self.test_to_address_2
+ _personal_info_to.issuer_address = self.test_issuer_address
+ _personal_info_to._personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ } # latest data
+ db.add(_personal_info_to)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"to_address_name": "テスト太郎1"}, # test_from_address_1's name
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 1, "offset": None, "limit": None, "total": 2},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": {
+ "key_manager": "key_manager_test1",
+ "name": "テスト太郎1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "amount": 0,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: amount (EQUAL)
+ def test_normal_3_7_1(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 10
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 20
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 30
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"amount": 20},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 1, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 20,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: amount (GTE)
+ def test_normal_3_7_2(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 10
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 20
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 30
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"amount": 20, "amount_operator": 1},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 2, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 30,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 20,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: amount (LTE)
+ def test_normal_3_7_3(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 10
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 20
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 30
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"amount": 20, "amount_operator": 2},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 2, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 10,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 20,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: source_event
+ def test_normal_3_8(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_2
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_2
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 2
+ _idx_transfer.source_event = IDXTransferSourceEventType.UNLOCK.value
+ _idx_transfer.data = {"message": "unlock"}
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"source_event": IDXTransferSourceEventType.UNLOCK.value},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 1, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.UNLOCK.value,
+ "data": {"message": "unlock"},
+ "block_timestamp": self.test_block_timestamp_str[2],
+ }
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: data
+ def test_normal_3_9(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_2
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_2
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 2
+ _idx_transfer.source_event = IDXTransferSourceEventType.UNLOCK.value
+ _idx_transfer.data = {"message": "unlock"}
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address), params={"data": "unlo"}
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 1, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.UNLOCK.value,
+ "data": {"message": "unlock"},
+ "block_timestamp": self.test_block_timestamp_str[2],
+ }
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # sort: block_timestamp ASC
+ def test_normal_4_1(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ for i in range(0, 3):
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = i
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[i]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={
+ "sort_item": "block_timestamp",
+ "sort_order": 0,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 3, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 1,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 0,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # sort: from_address ASC
+ def test_normal_4_2(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_2
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_2
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 2
+ _idx_transfer.source_event = IDXTransferSourceEventType.UNLOCK.value
+ _idx_transfer.data = {"message": "unlock"}
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={
+ "sort_item": "from_address",
+ "sort_order": 0,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 3, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.UNLOCK.value,
+ "data": {"message": "unlock"},
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_2,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 0,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_2,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 1,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # sort: to_address DESC
+ def test_normal_4_3(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_2
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 2
+ _idx_transfer.source_event = IDXTransferSourceEventType.UNLOCK.value
+ _idx_transfer.data = {"message": "unlock"}
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={
+ "sort_item": "to_address",
+ "sort_order": 1,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 3, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_2,
+ "to_address_personal_information": None,
+ "amount": 0,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.UNLOCK.value,
+ "data": {"message": "unlock"},
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 1,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # sort: from_address_name DESC
+ def test_normal_4_4(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_2
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ # prepare data: IDXPersonalInfo
+ _personal_info_from = IDXPersonalInfo()
+ _personal_info_from.account_address = self.test_from_address_1
+ _personal_info_from.issuer_address = self.test_issuer_address
+ _personal_info_from._personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "テスト太郎1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ } # latest data
+ db.add(_personal_info_from)
+
+ _personal_info_to = IDXPersonalInfo()
+ _personal_info_to.account_address = self.test_from_address_2
+ _personal_info_to.issuer_address = self.test_issuer_address
+ _personal_info_to._personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "テスト太郎2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ } # latest data
+ db.add(_personal_info_to)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={
+ "sort_item": "from_address_name",
+ "sort_order": 1,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 2, "offset": None, "limit": None, "total": 2},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_2,
+ "from_address_personal_information": {
+ "address": "address_test2",
+ "birth": "birth_test2",
+ "email": "email_test2",
+ "is_corporate": False,
+ "key_manager": "key_manager_test2",
+ "name": "テスト太郎2",
+ "postal_code": "postal_code_test2",
+ "tax_category": 10,
+ },
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 1,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": {
+ "address": "address_test1",
+ "birth": "birth_test1",
+ "email": "email_test1",
+ "is_corporate": False,
+ "key_manager": "key_manager_test1",
+ "name": "テスト太郎1",
+ "postal_code": "postal_code_test1",
+ "tax_category": 10,
+ },
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 0,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # sort: to_address_name DESC
+ def test_normal_4_5(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_2
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ # prepare data: IDXPersonalInfo
+ _personal_info_from = IDXPersonalInfo()
+ _personal_info_from.account_address = self.test_to_address_1
+ _personal_info_from.issuer_address = self.test_issuer_address
+ _personal_info_from._personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "テスト太郎1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ } # latest data
+ db.add(_personal_info_from)
+
+ _personal_info_to = IDXPersonalInfo()
+ _personal_info_to.account_address = self.test_to_address_2
+ _personal_info_to.issuer_address = self.test_issuer_address
+ _personal_info_to._personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "テスト太郎2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ } # latest data
+ db.add(_personal_info_to)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={
+ "sort_item": "to_address_name",
+ "sort_order": 1,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 2, "offset": None, "limit": None, "total": 2},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_2,
+ "to_address_personal_information": {
+ "address": "address_test2",
+ "birth": "birth_test2",
+ "email": "email_test2",
+ "is_corporate": False,
+ "key_manager": "key_manager_test2",
+ "name": "テスト太郎2",
+ "postal_code": "postal_code_test2",
+ "tax_category": 10,
+ },
+ "amount": 1,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": {
+ "address": "address_test1",
+ "birth": "birth_test1",
+ "email": "email_test1",
+ "is_corporate": False,
+ "key_manager": "key_manager_test1",
+ "name": "テスト太郎1",
+ "postal_code": "postal_code_test1",
+ "tax_category": 10,
+ },
+ "amount": 0,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # sort: amount DESC
+ def test_normal_4_6(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 2
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 2
+ _idx_transfer.source_event = IDXTransferSourceEventType.UNLOCK.value
+ _idx_transfer.data = {"message": "unlock"}
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={
+ "sort_item": "amount",
+ "sort_order": 0,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 3, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 1,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.UNLOCK.value,
+ "data": {"message": "unlock"},
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ ###########################################################################
+ # Error Case
+ ###########################################################################
+
+ #
+ # token not found
+ def test_error_1(self, client, db):
+ # request target API
+ resp = client.get(self.base_url.format(self.test_token_address))
+
+ # assertion
+ assert resp.status_code == 404
+ assumed_response = {
+ "meta": {"code": 1, "title": "NotFound"},
+ "detail": "token not found",
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # processing token
+ def test_error_2(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.token_status = 0
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(self.base_url.format(self.test_token_address))
+
+ # assertion
+ assert resp.status_code == 400
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "InvalidParameterError"},
+ "detail": "this token is temporarily unavailable",
+ }
+
+ #
+ # param error: sort_item
+ def test_error_3(self, client, db):
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"sort_item": "block_timestamp12345"},
+ )
+
+ # assertion
+ assert resp.status_code == 422
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "type": "enum",
+ "loc": ["query", "sort_item"],
+ "msg": "Input should be 'block_timestamp', 'from_address', 'to_address', 'from_address_name', 'to_address_name' or 'amount'",
+ "input": "block_timestamp12345",
+ "ctx": {
+ "expected": "'block_timestamp', 'from_address', 'to_address', 'from_address_name', 'to_address_name' or 'amount'"
+ },
+ }
+ ],
+ }
+
+ #
+ # param error: sort_order(min)
+ def test_error_4(self, client, db):
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address), params={"sort_order": -1}
+ )
+
+ # assertion
+ assert resp.status_code == 422
+ assumed_response = {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "ctx": {"expected": "0 or 1"},
+ "input": "-1",
+ "loc": ["query", "sort_order"],
+ "msg": "Input should be 0 or 1",
+ "type": "enum",
+ }
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # param error: sort_order(max)
+ def test_error_5(self, client, db):
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address), params={"sort_order": 2}
+ )
+
+ # assertion
+ assert resp.status_code == 422
+ assumed_response = {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "ctx": {"expected": "0 or 1"},
+ "input": "2",
+ "loc": ["query", "sort_order"],
+ "msg": "Input should be 0 or 1",
+ "type": "enum",
+ }
+ ],
+ }
+ assert resp.json() == assumed_response
diff --git a/tests/test_app_routers_docs_GET.py b/tests/app/test_docs_GET.py
similarity index 100%
rename from tests/test_app_routers_docs_GET.py
rename to tests/app/test_docs_GET.py
diff --git a/tests/test_app_routers_e2e_messaging_accounts_GET.py b/tests/app/test_e2e_messaging_accounts_GET.py
similarity index 92%
rename from tests/test_app_routers_e2e_messaging_accounts_GET.py
rename to tests/app/test_e2e_messaging_accounts_GET.py
index 788304f4..1ec9e09e 100644
--- a/tests/test_app_routers_e2e_messaging_accounts_GET.py
+++ b/tests/app/test_e2e_messaging_accounts_GET.py
@@ -18,7 +18,7 @@
"""
import time
-from datetime import datetime
+from datetime import UTC, datetime
from app.model.db import E2EMessagingAccount, E2EMessagingAccountRsaKey
@@ -56,7 +56,7 @@ def test_normal_2(self, client, db):
_rsa_key = E2EMessagingAccountRsaKey()
_rsa_key.account_address = "0x1234567890123456789012345678900000000000"
_rsa_key.rsa_public_key = "rsa_public_key_1_1"
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
@@ -90,7 +90,7 @@ def test_normal_3(self, client, db):
_rsa_key = E2EMessagingAccountRsaKey()
_rsa_key.account_address = "0x1234567890123456789012345678900000000000"
_rsa_key.rsa_public_key = "rsa_public_key_1_1"
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
@@ -110,7 +110,7 @@ def test_normal_3(self, client, db):
_rsa_key = E2EMessagingAccountRsaKey()
_rsa_key.account_address = "0x1234567890123456789012345678900000000002"
_rsa_key.rsa_public_key = "rsa_public_key_2_1"
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
@@ -121,21 +121,21 @@ def test_normal_3(self, client, db):
_rsa_key = E2EMessagingAccountRsaKey()
_rsa_key.account_address = "0x1234567890123456789012345678900000000003"
_rsa_key.rsa_public_key = "rsa_public_key_3_1"
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
_rsa_key = E2EMessagingAccountRsaKey()
_rsa_key.account_address = "0x1234567890123456789012345678900000000003"
_rsa_key.rsa_public_key = "rsa_public_key_3_2"
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
_rsa_key = E2EMessagingAccountRsaKey()
_rsa_key.account_address = "0x1234567890123456789012345678900000000003"
_rsa_key.rsa_public_key = "rsa_public_key_3_3"
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
diff --git a/tests/test_app_routers_e2e_messaging_accounts_POST.py b/tests/app/test_e2e_messaging_accounts_POST.py
similarity index 98%
rename from tests/test_app_routers_e2e_messaging_accounts_POST.py
rename to tests/app/test_e2e_messaging_accounts_POST.py
index fbb4033f..0e617eed 100644
--- a/tests/test_app_routers_e2e_messaging_accounts_POST.py
+++ b/tests/app/test_e2e_messaging_accounts_POST.py
@@ -18,7 +18,7 @@
"""
import base64
-from datetime import datetime, timezone
+from datetime import UTC, datetime
from unittest import mock
from unittest.mock import ANY, MagicMock
@@ -70,7 +70,7 @@ def test_normal_1(self, client, db, e2e_messaging_contract):
{
"number": 12345,
"timestamp": datetime(
- 2099, 4, 27, 12, 34, 56, tzinfo=timezone.utc
+ 2099, 4, 27, 12, 34, 56, tzinfo=UTC
).timestamp(),
},
],
@@ -172,7 +172,7 @@ def generate_random(self, NumberOfBytes):
{
"number": 12345,
"timestamp": datetime(
- 2099, 4, 27, 12, 34, 56, tzinfo=timezone.utc
+ 2099, 4, 27, 12, 34, 56, tzinfo=UTC
).timestamp(),
},
],
diff --git a/tests/test_app_routers_e2e_messaging_accounts_{account_address}_DELETE.py b/tests/app/test_e2e_messaging_accounts_{account_address}_DELETE.py
similarity index 93%
rename from tests/test_app_routers_e2e_messaging_accounts_{account_address}_DELETE.py
rename to tests/app/test_e2e_messaging_accounts_{account_address}_DELETE.py
index 031b2114..088099a3 100644
--- a/tests/test_app_routers_e2e_messaging_accounts_{account_address}_DELETE.py
+++ b/tests/app/test_e2e_messaging_accounts_{account_address}_DELETE.py
@@ -18,7 +18,7 @@
"""
import time
-from datetime import datetime
+from datetime import UTC, datetime
from sqlalchemy import select
@@ -46,21 +46,21 @@ def test_normal_1(self, client, db):
_rsa_key = E2EMessagingAccountRsaKey()
_rsa_key.account_address = "0x1234567890123456789012345678900000000000"
_rsa_key.rsa_public_key = "rsa_public_key_1_1"
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
_rsa_key = E2EMessagingAccountRsaKey()
_rsa_key.account_address = "0x1234567890123456789012345678900000000000"
_rsa_key.rsa_public_key = "rsa_public_key_1_2"
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
_rsa_key = E2EMessagingAccountRsaKey()
_rsa_key.account_address = "0x1234567890123456789012345678900000000000"
_rsa_key.rsa_public_key = "rsa_public_key_1_3"
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
diff --git a/tests/test_app_routers_e2e_messaging_accounts_{account_address}_GET.py b/tests/app/test_e2e_messaging_accounts_{account_address}_GET.py
similarity index 93%
rename from tests/test_app_routers_e2e_messaging_accounts_{account_address}_GET.py
rename to tests/app/test_e2e_messaging_accounts_{account_address}_GET.py
index f5643bf2..54ec0b3c 100644
--- a/tests/test_app_routers_e2e_messaging_accounts_{account_address}_GET.py
+++ b/tests/app/test_e2e_messaging_accounts_{account_address}_GET.py
@@ -18,7 +18,7 @@
"""
import time
-from datetime import datetime
+from datetime import UTC, datetime
from app.model.db import E2EMessagingAccount, E2EMessagingAccountRsaKey
@@ -43,21 +43,21 @@ def test_normal_1(self, client, db):
_rsa_key = E2EMessagingAccountRsaKey()
_rsa_key.account_address = "0x1234567890123456789012345678900000000000"
_rsa_key.rsa_public_key = "rsa_public_key_1_1"
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
_rsa_key = E2EMessagingAccountRsaKey()
_rsa_key.account_address = "0x1234567890123456789012345678900000000000"
_rsa_key.rsa_public_key = "rsa_public_key_1_2"
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
_rsa_key = E2EMessagingAccountRsaKey()
_rsa_key.account_address = "0x1234567890123456789012345678900000000000"
_rsa_key.rsa_public_key = "rsa_public_key_1_3"
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
diff --git a/tests/test_app_routers_e2e_messaging_accounts_{account_address}_eoa_password_POST.py b/tests/app/test_e2e_messaging_accounts_{account_address}_eoa_password_POST.py
similarity index 100%
rename from tests/test_app_routers_e2e_messaging_accounts_{account_address}_eoa_password_POST.py
rename to tests/app/test_e2e_messaging_accounts_{account_address}_eoa_password_POST.py
diff --git a/tests/test_app_routers_e2e_messaging_accounts_{account_address}_rsa_key_POST.py b/tests/app/test_e2e_messaging_accounts_{account_address}_rsa_key_POST.py
similarity index 94%
rename from tests/test_app_routers_e2e_messaging_accounts_{account_address}_rsa_key_POST.py
rename to tests/app/test_e2e_messaging_accounts_{account_address}_rsa_key_POST.py
index 2ca489cc..8b9e1025 100644
--- a/tests/test_app_routers_e2e_messaging_accounts_{account_address}_rsa_key_POST.py
+++ b/tests/app/test_e2e_messaging_accounts_{account_address}_rsa_key_POST.py
@@ -18,7 +18,7 @@
"""
import time
-from datetime import datetime
+from datetime import UTC, datetime
from sqlalchemy import select
@@ -43,21 +43,21 @@ def test_normal_1(self, client, db):
_rsa_key = E2EMessagingAccountRsaKey()
_rsa_key.account_address = "0x1234567890123456789012345678900000000000"
_rsa_key.rsa_public_key = "rsa_public_key_1_1"
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
_rsa_key = E2EMessagingAccountRsaKey()
_rsa_key.account_address = "0x1234567890123456789012345678900000000000"
_rsa_key.rsa_public_key = "rsa_public_key_1_2"
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
_rsa_key = E2EMessagingAccountRsaKey()
_rsa_key.account_address = "0x1234567890123456789012345678900000000000"
_rsa_key.rsa_public_key = "rsa_public_key_1_3"
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
@@ -99,21 +99,21 @@ def test_normal_2(self, client, db):
_rsa_key = E2EMessagingAccountRsaKey()
_rsa_key.account_address = "0x1234567890123456789012345678900000000000"
_rsa_key.rsa_public_key = "rsa_public_key_1_1"
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
_rsa_key = E2EMessagingAccountRsaKey()
_rsa_key.account_address = "0x1234567890123456789012345678900000000000"
_rsa_key.rsa_public_key = "rsa_public_key_1_2"
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
_rsa_key = E2EMessagingAccountRsaKey()
_rsa_key.account_address = "0x1234567890123456789012345678900000000000"
_rsa_key.rsa_public_key = "rsa_public_key_1_3"
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
diff --git a/tests/test_app_routers_e2e_messaging_accounts_{account_address}_rsa_passphrase_POST.py b/tests/app/test_e2e_messaging_accounts_{account_address}_rsa_passphrase_POST.py
similarity index 97%
rename from tests/test_app_routers_e2e_messaging_accounts_{account_address}_rsa_passphrase_POST.py
rename to tests/app/test_e2e_messaging_accounts_{account_address}_rsa_passphrase_POST.py
index bb598a3f..84428bba 100644
--- a/tests/test_app_routers_e2e_messaging_accounts_{account_address}_rsa_passphrase_POST.py
+++ b/tests/app/test_e2e_messaging_accounts_{account_address}_rsa_passphrase_POST.py
@@ -18,7 +18,7 @@
"""
import time
-from datetime import datetime
+from datetime import UTC, datetime
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
@@ -122,7 +122,7 @@ def test_normal_1(self, client, db, e2e_messaging_contract):
_rsa_key.account_address = user_address_1
_rsa_key.rsa_private_key = "rsa_private_key_1_1"
_rsa_key.rsa_passphrase = E2EEUtils.encrypt("password_1")
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
@@ -130,7 +130,7 @@ def test_normal_1(self, client, db, e2e_messaging_contract):
_rsa_key.account_address = user_address_1
_rsa_key.rsa_private_key = "rsa_private_key_1_2"
_rsa_key.rsa_passphrase = E2EEUtils.encrypt("password_2")
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
@@ -138,7 +138,7 @@ def test_normal_1(self, client, db, e2e_messaging_contract):
_rsa_key.account_address = user_address_1
_rsa_key.rsa_private_key = self.rsa_private_key
_rsa_key.rsa_passphrase = E2EEUtils.encrypt(old_passphrase)
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
time.sleep(1)
@@ -359,7 +359,7 @@ def test_normal_3(self, client, db, e2e_messaging_contract):
_rsa_key.account_address = user_address_1
_rsa_key.rsa_private_key = self.rsa_private_key
_rsa_key.rsa_passphrase = E2EEUtils.encrypt(old_passphrase)
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
db.commit()
@@ -400,7 +400,7 @@ def test_normal_4(self, client, db, e2e_messaging_contract):
_rsa_key.account_address = user_address_1
_rsa_key.rsa_private_key = self.rsa_private_key
_rsa_key.rsa_passphrase = E2EEUtils.encrypt(old_passphrase)
- _rsa_key.block_timestamp = datetime.utcnow()
+ _rsa_key.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key)
db.commit()
diff --git a/tests/test_app_routers_e2e_messaging_messages_GET.py b/tests/app/test_e2e_messaging_messages_GET.py
similarity index 100%
rename from tests/test_app_routers_e2e_messaging_messages_GET.py
rename to tests/app/test_e2e_messaging_messages_GET.py
diff --git a/tests/test_app_routers_e2e_messaging_messages_{id}_GET.py b/tests/app/test_e2e_messaging_messages_{id}_GET.py
similarity index 100%
rename from tests/test_app_routers_e2e_messaging_messages_{id}_GET.py
rename to tests/app/test_e2e_messaging_messages_{id}_GET.py
diff --git a/tests/test_app_routers_e2ee_GET.py b/tests/app/test_e2ee_GET.py
similarity index 100%
rename from tests/test_app_routers_e2ee_GET.py
rename to tests/app/test_e2ee_GET.py
diff --git a/tests/test_app_routers_files_GET.py b/tests/app/test_files_GET.py
similarity index 100%
rename from tests/test_app_routers_files_GET.py
rename to tests/app/test_files_GET.py
diff --git a/tests/test_app_routers_files_POST.py b/tests/app/test_files_POST.py
similarity index 100%
rename from tests/test_app_routers_files_POST.py
rename to tests/app/test_files_POST.py
diff --git a/tests/test_app_routers_files_{file_id}_DELETE.py b/tests/app/test_files_{file_id}_DELETE.py
similarity index 100%
rename from tests/test_app_routers_files_{file_id}_DELETE.py
rename to tests/app/test_files_{file_id}_DELETE.py
diff --git a/tests/test_app_routers_files_{file_id}_GET.py b/tests/app/test_files_{file_id}_GET.py
similarity index 100%
rename from tests/test_app_routers_files_{file_id}_GET.py
rename to tests/app/test_files_{file_id}_GET.py
diff --git a/tests/test_app_routers_freezelog_ChangeFreezeLogAccountPassword.py b/tests/app/test_freezelog_ChangeFreezeLogAccountPassword.py
similarity index 100%
rename from tests/test_app_routers_freezelog_ChangeFreezeLogAccountPassword.py
rename to tests/app/test_freezelog_ChangeFreezeLogAccountPassword.py
diff --git a/tests/test_app_routers_freezelog_CreateFreezeLogAccount.py b/tests/app/test_freezelog_CreateFreezeLogAccount.py
similarity index 100%
rename from tests/test_app_routers_freezelog_CreateFreezeLogAccount.py
rename to tests/app/test_freezelog_CreateFreezeLogAccount.py
diff --git a/tests/test_app_routers_freezelog_DeleteFreezeLogAccount.py b/tests/app/test_freezelog_DeleteFreezeLogAccount.py
similarity index 100%
rename from tests/test_app_routers_freezelog_DeleteFreezeLogAccount.py
rename to tests/app/test_freezelog_DeleteFreezeLogAccount.py
diff --git a/tests/test_app_routers_freezelog_ListAllFreezeLogAccount.py b/tests/app/test_freezelog_ListAllFreezeLogAccount.py
similarity index 100%
rename from tests/test_app_routers_freezelog_ListAllFreezeLogAccount.py
rename to tests/app/test_freezelog_ListAllFreezeLogAccount.py
diff --git a/tests/test_app_routers_freezelog_RecordNewFreezeLog.py b/tests/app/test_freezelog_RecordNewFreezeLog.py
similarity index 100%
rename from tests/test_app_routers_freezelog_RecordNewFreezeLog.py
rename to tests/app/test_freezelog_RecordNewFreezeLog.py
diff --git a/tests/test_app_routers_freezelog_RetriveFreezeLog.py b/tests/app/test_freezelog_RetriveFreezeLog.py
similarity index 100%
rename from tests/test_app_routers_freezelog_RetriveFreezeLog.py
rename to tests/app/test_freezelog_RetriveFreezeLog.py
diff --git a/tests/test_app_routers_freezelog_UpdateFreezeLog.py b/tests/app/test_freezelog_UpdateFreezeLog.py
similarity index 100%
rename from tests/test_app_routers_freezelog_UpdateFreezeLog.py
rename to tests/app/test_freezelog_UpdateFreezeLog.py
diff --git a/tests/test_app_routers_healthcheck_GET.py b/tests/app/test_healthcheck_GET.py
similarity index 99%
rename from tests/test_app_routers_healthcheck_GET.py
rename to tests/app/test_healthcheck_GET.py
index bc096137..e35fa859 100644
--- a/tests/test_app_routers_healthcheck_GET.py
+++ b/tests/app/test_healthcheck_GET.py
@@ -92,7 +92,6 @@ def test_error_1(self, client, db):
# request target api
resp = client.get(self.apiurl)
- print(resp.json())
# assertion
assert resp.status_code == 503
assert resp.json() == {
diff --git a/tests/test_app_routers_ledger_{token_address}_details_data_GET.py b/tests/app/test_ledger_{token_address}_details_data_GET.py
similarity index 98%
rename from tests/test_app_routers_ledger_{token_address}_details_data_GET.py
rename to tests/app/test_ledger_{token_address}_details_data_GET.py
index 16e117d1..5c84b770 100644
--- a/tests/test_app_routers_ledger_{token_address}_details_data_GET.py
+++ b/tests/app/test_ledger_{token_address}_details_data_GET.py
@@ -45,7 +45,7 @@ def test_normal_1_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_details_data_1_1 = LedgerDetailsData()
@@ -161,7 +161,7 @@ def test_normal_1_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_details_data_1_1 = LedgerDetailsData()
@@ -274,7 +274,7 @@ def test_normal_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_details_data_1_1 = LedgerDetailsData()
@@ -416,7 +416,7 @@ def test_error_2_1(self, client, db):
_token.token_address = token_address
_token.abi = {}
_token.token_status = 2
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -477,7 +477,7 @@ def test_error_3(self, client, db):
_token.token_address = token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
diff --git a/tests/test_app_routers_ledger_{token_address}_details_data_POST.py b/tests/app/test_ledger_{token_address}_details_data_POST.py
similarity index 99%
rename from tests/test_app_routers_ledger_{token_address}_details_data_POST.py
rename to tests/app/test_ledger_{token_address}_details_data_POST.py
index 974b0fec..dc0ac3db 100644
--- a/tests/test_app_routers_ledger_{token_address}_details_data_POST.py
+++ b/tests/app/test_ledger_{token_address}_details_data_POST.py
@@ -46,7 +46,7 @@ def test_normal_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -118,7 +118,7 @@ def test_normal_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -413,7 +413,7 @@ def test_error_5(self, client, db):
_token.token_address = token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
diff --git a/tests/test_app_routers_ledger_{token_address}_details_data_{data_id}_DELETE.py b/tests/app/test_ledger_{token_address}_details_data_{data_id}_DELETE.py
similarity index 98%
rename from tests/test_app_routers_ledger_{token_address}_details_data_{data_id}_DELETE.py
rename to tests/app/test_ledger_{token_address}_details_data_{data_id}_DELETE.py
index 01febd2a..2362ea1a 100644
--- a/tests/test_app_routers_ledger_{token_address}_details_data_{data_id}_DELETE.py
+++ b/tests/app/test_ledger_{token_address}_details_data_{data_id}_DELETE.py
@@ -45,7 +45,7 @@ def test_normal_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_details_1_data_1 = LedgerDetailsData()
@@ -196,7 +196,7 @@ def test_error_4(self, client, db):
_token.token_address = token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
diff --git a/tests/test_app_routers_ledger_{token_address}_details_data_{data_id}_GET.py b/tests/app/test_ledger_{token_address}_details_data_{data_id}_GET.py
similarity index 98%
rename from tests/test_app_routers_ledger_{token_address}_details_data_{data_id}_GET.py
rename to tests/app/test_ledger_{token_address}_details_data_{data_id}_GET.py
index bbdfda28..14be1c94 100644
--- a/tests/test_app_routers_ledger_{token_address}_details_data_{data_id}_GET.py
+++ b/tests/app/test_ledger_{token_address}_details_data_{data_id}_GET.py
@@ -44,7 +44,7 @@ def test_normal_1_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_details_1_data_1 = LedgerDetailsData()
@@ -127,7 +127,7 @@ def test_normal_1_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_details_1_data_1 = LedgerDetailsData()
@@ -207,7 +207,7 @@ def test_normal_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_details_1_data_1 = LedgerDetailsData()
@@ -326,7 +326,7 @@ def test_error_2_1(self, client, db):
_token.token_address = token_address
_token.abi = {}
_token.token_status = 2
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -381,7 +381,7 @@ def test_error_3(self, client, db):
_token.token_address = token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
diff --git a/tests/test_app_routers_ledger_{token_address}_details_data_{data_id}_POST.py b/tests/app/test_ledger_{token_address}_details_data_{data_id}_POST.py
similarity index 99%
rename from tests/test_app_routers_ledger_{token_address}_details_data_{data_id}_POST.py
rename to tests/app/test_ledger_{token_address}_details_data_{data_id}_POST.py
index 4f37882e..f820d3d0 100644
--- a/tests/test_app_routers_ledger_{token_address}_details_data_{data_id}_POST.py
+++ b/tests/app/test_ledger_{token_address}_details_data_{data_id}_POST.py
@@ -49,7 +49,7 @@ def test_normal_1(self, mock_func, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_details_1_data_1 = LedgerDetailsData()
@@ -134,7 +134,7 @@ def test_normal_2(self, mock_func, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_details_1_data_1 = LedgerDetailsData()
@@ -445,7 +445,7 @@ def test_error_5(self, client, db):
_token.token_address = token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
diff --git a/tests/test_app_routers_ledger_{token_address}_history_GET.py b/tests/app/test_ledger_{token_address}_history_GET.py
similarity index 98%
rename from tests/test_app_routers_ledger_{token_address}_history_GET.py
rename to tests/app/test_ledger_{token_address}_history_GET.py
index b15e436e..83071bc8 100644
--- a/tests/test_app_routers_ledger_{token_address}_history_GET.py
+++ b/tests/app/test_ledger_{token_address}_history_GET.py
@@ -45,7 +45,7 @@ def test_normal_1_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_ledger_1 = Ledger()
@@ -110,7 +110,7 @@ def test_normal_1_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_ledger_1 = Ledger()
@@ -172,7 +172,7 @@ def test_normal_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_ledger_1 = Ledger()
@@ -291,7 +291,7 @@ def test_error_2_1(self, client, db):
_token.token_address = token_address
_token.abi = {}
_token.token_status = 2
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# request target API
@@ -350,7 +350,7 @@ def test_error_3(self, client, db):
_token.token_address = token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
diff --git a/tests/test_app_routers_ledger_{token_address}_history_{ledger_id}_GET.py b/tests/app/test_ledger_{token_address}_history_{ledger_id}_GET.py
similarity index 60%
rename from tests/test_app_routers_ledger_{token_address}_history_{ledger_id}_GET.py
rename to tests/app/test_ledger_{token_address}_history_{ledger_id}_GET.py
index c1e65ae9..5a6d0206 100644
--- a/tests/test_app_routers_ledger_{token_address}_history_{ledger_id}_GET.py
+++ b/tests/app/test_ledger_{token_address}_history_{ledger_id}_GET.py
@@ -58,7 +58,7 @@ def test_normal_1_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_ledger_1 = Ledger()
@@ -100,8 +100,8 @@ def test_normal_1_1(self, client, db):
},
{
"account_address": account_address_2,
- "name": "name_test_2",
- "address": "address_test_2",
+ "name": None,
+ "address": None,
"amount": 100,
"price": 200,
"balance": 300,
@@ -115,6 +115,7 @@ def test_normal_1_1(self, client, db):
},
{"f-test1": "a", "f-test2": "b"},
],
+ "some_personal_info_not_registered": True,
},
{
"token_detail_type": "権利_test_2",
@@ -152,6 +153,7 @@ def test_normal_1_1(self, client, db):
},
{"f-test1-1": "a", "f-test2-1": "b"},
],
+ "some_personal_info_not_registered": False,
},
],
"footers": [
@@ -172,7 +174,7 @@ def test_normal_1_1(self, client, db):
db.commit()
- # request target AsPI
+ # request target API
resp = client.get(
self.base_url.format(token_address=token_address, ledger_id=1),
params={
@@ -221,8 +223,8 @@ def test_normal_1_1(self, client, db):
},
{
"account_address": account_address_2,
- "name": "name_test_2",
- "address": "address_test_2",
+ "name": None,
+ "address": None,
"amount": 100,
"price": 200,
"balance": 300,
@@ -236,6 +238,7 @@ def test_normal_1_1(self, client, db):
},
{"f-test1": "a", "f-test2": "b"},
],
+ "some_personal_info_not_registered": True,
},
{
"token_detail_type": "権利_test_2",
@@ -273,6 +276,7 @@ def test_normal_1_1(self, client, db):
},
{"f-test1-1": "a", "f-test2-1": "b"},
],
+ "some_personal_info_not_registered": False,
},
],
"footers": [
@@ -303,7 +307,7 @@ def test_normal_1_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_ledger_1 = Ledger()
@@ -360,6 +364,7 @@ def test_normal_1_2(self, client, db):
},
{"f-test1": "a", "f-test2": "b"},
],
+ "some_personal_info_not_registered": False,
},
{
"token_detail_type": "権利_test_2",
@@ -397,6 +402,7 @@ def test_normal_1_2(self, client, db):
},
{"f-test1-1": "a", "f-test2-1": "b"},
],
+ "some_personal_info_not_registered": False,
},
],
"footers": [
@@ -417,7 +423,7 @@ def test_normal_1_2(self, client, db):
db.commit()
- # request target AsPI
+ # request target API
resp = client.get(
self.base_url.format(token_address=token_address, ledger_id=1),
params={
@@ -478,6 +484,7 @@ def test_normal_1_2(self, client, db):
},
{"f-test1": "a", "f-test2": "b"},
],
+ "some_personal_info_not_registered": False,
},
{
"token_detail_type": "権利_test_2",
@@ -515,6 +522,7 @@ def test_normal_1_2(self, client, db):
},
{"f-test1-1": "a", "f-test2-1": "b"},
],
+ "some_personal_info_not_registered": False,
},
],
"footers": [
@@ -529,11 +537,10 @@ def test_normal_1_2(self, client, db):
],
}
- #
- # latest_flg = 1 (Get the latest personal info)
- # address_1 has personal info in the DB
- # address_2 has no personal info in the DB
- def test_normal_2_1(self, client, db):
+ #
+ # latest_flg = 0 (Get the latest personal info)
+ # - ledger detail contains None value in "name" and "value": some_personal_info_not_registered = True
+ def test_normal_2(self, client, db):
user_1 = config_eth_account("user1")
issuer_address = user_1["address"]
token_address = "0xABCdeF1234567890abcdEf123456789000000000"
@@ -548,7 +555,7 @@ def test_normal_2_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_ledger_1 = Ledger()
@@ -581,8 +588,8 @@ def test_normal_2_1(self, client, db):
"data": [
{
"account_address": account_address_1,
- "name": "name_test_1",
- "address": "address_test_1",
+ "name": None,
+ "address": None,
"amount": 10,
"price": 20,
"balance": 30,
@@ -605,6 +612,7 @@ def test_normal_2_1(self, client, db):
},
{"f-test1": "a", "f-test2": "b"},
],
+ "some_personal_info_not_registered": True,
},
{
"token_detail_type": "権利_test_2",
@@ -642,6 +650,7 @@ def test_normal_2_1(self, client, db):
},
{"f-test1-1": "a", "f-test2-1": "b"},
],
+ "some_personal_info_not_registered": False,
},
],
"footers": [
@@ -660,17 +669,6 @@ def test_normal_2_1(self, client, db):
) # JST 2022/01/02
db.add(_ledger_1)
- _idx_personal_info_1 = (
- IDXPersonalInfo()
- ) # Note: account_address_1 has personal information in DB
- _idx_personal_info_1.account_address = account_address_1
- _idx_personal_info_1.issuer_address = issuer_address
- _idx_personal_info_1.personal_info = {
- "name": "name_db_1",
- "address": "address_db_1",
- }
- db.add(_idx_personal_info_1)
-
_details_1 = LedgerDetailsTemplate()
_details_1.token_address = token_address
_details_1.token_detail_type = "権利_test_1"
@@ -698,38 +696,17 @@ def test_normal_2_1(self, client, db):
token = IbetStraightBondContract()
token.personal_info_contract_address = personal_info_contract_address
token.issuer_address = issuer_address
- token_get_mock = mock.patch(
- "app.model.blockchain.IbetStraightBondContract.get", return_value=token
- )
- personal_get_info_mock = mock.patch(
- "app.model.blockchain.PersonalInfoContract.get_info"
- )
# request target API
- with token_get_mock as token_get_mock_patch, personal_get_info_mock as personal_get_info_mock_patch:
- # Note:
- # account_address_2 has no personal information in the DB
- # and gets information from the contract
- personal_get_info_mock_patch.side_effect = [
- {
- "name": "name_contract_2",
- "address": "address_contract_2",
- }
- ]
-
- resp = client.get(
- self.base_url.format(token_address=token_address, ledger_id=1),
- params={
- "latest_flg": 1,
- },
- headers={
- "issuer-address": issuer_address,
- },
- )
- # assertion
- personal_get_info_mock_patch.assert_has_calls(
- [call(account_address=account_address_2, default_value=None)]
- )
+ resp = client.get(
+ self.base_url.format(token_address=token_address, ledger_id=1),
+ params={
+ "latest_flg": 0,
+ },
+ headers={
+ "issuer-address": issuer_address,
+ },
+ )
# assertion
assert resp.status_code == 200
@@ -760,8 +737,8 @@ def test_normal_2_1(self, client, db):
"data": [
{
"account_address": account_address_1,
- "name": "name_db_1",
- "address": "address_db_1",
+ "name": None,
+ "address": None,
"amount": 10,
"price": 20,
"balance": 30,
@@ -769,8 +746,8 @@ def test_normal_2_1(self, client, db):
},
{
"account_address": account_address_2,
- "name": "name_contract_2",
- "address": "address_contract_2",
+ "name": "name_test_2",
+ "address": "address_test_2",
"amount": 100,
"price": 200,
"balance": 300,
@@ -784,6 +761,7 @@ def test_normal_2_1(self, client, db):
},
{"f-test1": "a", "f-test2": "b"},
],
+ "some_personal_info_not_registered": True,
},
{
"token_detail_type": "権利_test_2",
@@ -821,6 +799,7 @@ def test_normal_2_1(self, client, db):
},
{"f-test1-1": "a", "f-test2-1": "b"},
],
+ "some_personal_info_not_registered": False,
},
],
"footers": [
@@ -835,11 +814,12 @@ def test_normal_2_1(self, client, db):
],
}
- #
+ #
# latest_flg = 1 (Get the latest personal info)
- # address_1 has partial personal info in the DB
- # address_2 has no personal info in the DB
- def test_normal_2_2(self, client, db):
+ # - address_1 has personal info in the DB
+ # - address_2 has no personal info in the DB
+ # token.require_personal_info_registered = True
+ def test_normal_3_1(self, client, db):
user_1 = config_eth_account("user1")
issuer_address = user_1["address"]
token_address = "0xABCdeF1234567890abcdEf123456789000000000"
@@ -854,7 +834,7 @@ def test_normal_2_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_ledger_1 = Ledger()
@@ -911,6 +891,7 @@ def test_normal_2_2(self, client, db):
},
{"f-test1": "a", "f-test2": "b"},
],
+ "some_personal_info_not_registered": False,
},
{
"token_detail_type": "権利_test_2",
@@ -948,6 +929,7 @@ def test_normal_2_2(self, client, db):
},
{"f-test1-1": "a", "f-test2-1": "b"},
],
+ "some_personal_info_not_registered": False,
},
],
"footers": [
@@ -968,10 +950,13 @@ def test_normal_2_2(self, client, db):
_idx_personal_info_1 = (
IDXPersonalInfo()
- ) # Note: account_address_1 has partial personal information in DB
+ ) # Note: account_address_1 has personal information in DB
_idx_personal_info_1.account_address = account_address_1
_idx_personal_info_1.issuer_address = issuer_address
- _idx_personal_info_1.personal_info = {"name": None, "address": None}
+ _idx_personal_info_1.personal_info = {
+ "name": "name_db_1",
+ "address": "address_db_1",
+ }
db.add(_idx_personal_info_1)
_details_1 = LedgerDetailsTemplate()
@@ -1001,6 +986,7 @@ def test_normal_2_2(self, client, db):
token = IbetStraightBondContract()
token.personal_info_contract_address = personal_info_contract_address
token.issuer_address = issuer_address
+ token.require_personal_info_registered = True
token_get_mock = mock.patch(
"app.model.blockchain.IbetStraightBondContract.get", return_value=token
)
@@ -1063,9 +1049,8 @@ def test_normal_2_2(self, client, db):
"data": [
{
"account_address": account_address_1,
- # Value stored with None should be converted to empty string.
- "name": None,
- "address": None,
+ "name": "name_db_1",
+ "address": "address_db_1",
"amount": 10,
"price": 20,
"balance": 30,
@@ -1088,6 +1073,7 @@ def test_normal_2_2(self, client, db):
},
{"f-test1": "a", "f-test2": "b"},
],
+ "some_personal_info_not_registered": False,
},
{
"token_detail_type": "権利_test_2",
@@ -1125,6 +1111,7 @@ def test_normal_2_2(self, client, db):
},
{"f-test1-1": "a", "f-test2-1": "b"},
],
+ "some_personal_info_not_registered": False,
},
],
"footers": [
@@ -1139,10 +1126,12 @@ def test_normal_2_2(self, client, db):
],
}
- #
- # latest_flg = 0 (Get the latest personal info)
- # ledger detail contains None value in "name" and "value"
- def test_normal_3(self, client, db):
+ #
+ # latest_flg = 1 (Get the latest personal info)
+ # - address_1 has partial personal info in the DB
+ # - address_2 has no personal info in the DB
+ # token.require_personal_info_registered = True
+ def test_normal_3_2(self, client, db):
user_1 = config_eth_account("user1")
issuer_address = user_1["address"]
token_address = "0xABCdeF1234567890abcdEf123456789000000000"
@@ -1157,7 +1146,7 @@ def test_normal_3(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_ledger_1 = Ledger()
@@ -1190,8 +1179,8 @@ def test_normal_3(self, client, db):
"data": [
{
"account_address": account_address_1,
- "name": None,
- "address": None,
+ "name": "name_test_1",
+ "address": "address_test_1",
"amount": 10,
"price": 20,
"balance": 30,
@@ -1214,6 +1203,7 @@ def test_normal_3(self, client, db):
},
{"f-test1": "a", "f-test2": "b"},
],
+ "some_personal_info_not_registered": False,
},
{
"token_detail_type": "権利_test_2",
@@ -1251,6 +1241,7 @@ def test_normal_3(self, client, db):
},
{"f-test1-1": "a", "f-test2-1": "b"},
],
+ "some_personal_info_not_registered": False,
},
],
"footers": [
@@ -1269,6 +1260,14 @@ def test_normal_3(self, client, db):
) # JST 2022/01/02
db.add(_ledger_1)
+ _idx_personal_info_1 = (
+ IDXPersonalInfo()
+ ) # Note: account_address_1 has partial personal information in DB
+ _idx_personal_info_1.account_address = account_address_1
+ _idx_personal_info_1.issuer_address = issuer_address
+ _idx_personal_info_1.personal_info = {"name": "name_test_1", "address": None}
+ db.add(_idx_personal_info_1)
+
_details_1 = LedgerDetailsTemplate()
_details_1.token_address = token_address
_details_1.token_detail_type = "権利_test_1"
@@ -1296,17 +1295,39 @@ def test_normal_3(self, client, db):
token = IbetStraightBondContract()
token.personal_info_contract_address = personal_info_contract_address
token.issuer_address = issuer_address
+ token.require_personal_info_registered = True
+ token_get_mock = mock.patch(
+ "app.model.blockchain.IbetStraightBondContract.get", return_value=token
+ )
+ personal_get_info_mock = mock.patch(
+ "app.model.blockchain.PersonalInfoContract.get_info"
+ )
# request target API
- resp = client.get(
- self.base_url.format(token_address=token_address, ledger_id=1),
- params={
- "latest_flg": 0,
- },
- headers={
- "issuer-address": issuer_address,
- },
- )
+ with token_get_mock as token_get_mock_patch, personal_get_info_mock as personal_get_info_mock_patch:
+ # Note:
+ # account_address_2 has no personal information in the DB
+ # and gets information from the contract
+ personal_get_info_mock_patch.side_effect = [
+ {
+ "name": "name_contract_2",
+ "address": "address_contract_2",
+ }
+ ]
+
+ resp = client.get(
+ self.base_url.format(token_address=token_address, ledger_id=1),
+ params={
+ "latest_flg": 1,
+ },
+ headers={
+ "issuer-address": issuer_address,
+ },
+ )
+ # assertion
+ personal_get_info_mock_patch.assert_has_calls(
+ [call(account_address=account_address_2, default_value=None)]
+ )
# assertion
assert resp.status_code == 200
@@ -1337,8 +1358,7 @@ def test_normal_3(self, client, db):
"data": [
{
"account_address": account_address_1,
- # Value stored with None should be converted to empty string.
- "name": None,
+ "name": "name_test_1",
"address": None,
"amount": 10,
"price": 20,
@@ -1347,8 +1367,8 @@ def test_normal_3(self, client, db):
},
{
"account_address": account_address_2,
- "name": "name_test_2",
- "address": "address_test_2",
+ "name": "name_contract_2",
+ "address": "address_contract_2",
"amount": 100,
"price": 200,
"balance": 300,
@@ -1362,6 +1382,7 @@ def test_normal_3(self, client, db):
},
{"f-test1": "a", "f-test2": "b"},
],
+ "some_personal_info_not_registered": False,
},
{
"token_detail_type": "権利_test_2",
@@ -1399,6 +1420,7 @@ def test_normal_3(self, client, db):
},
{"f-test1-1": "a", "f-test2-1": "b"},
],
+ "some_personal_info_not_registered": False,
},
],
"footers": [
@@ -1413,14 +1435,16 @@ def test_normal_3(self, client, db):
],
}
- #
- # Test `currency` backward compatibility
- def test_normal_4(self, client, db):
+ #
+ # latest_flg = 1 (Get the latest personal info)
+ # token.require_personal_info_registered = False
+ # Personal information has not been indexed yet
+ def test_normal_3_3(self, client, db):
user_1 = config_eth_account("user1")
issuer_address = user_1["address"]
token_address = "0xABCdeF1234567890abcdEf123456789000000000"
account_address_1 = "0xABCdeF1234567890abCDeF123456789000000001"
- account_address_2 = "0xaBcdEF1234567890aBCDEF123456789000000002"
+ personal_info_contract_address = "0xabcDEF1234567890AbcDEf123456789000000003"
# prepare data
_token = Token()
@@ -1429,7 +1453,7 @@ def test_normal_4(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_ledger_1 = Ledger()
@@ -1438,6 +1462,7 @@ def test_normal_4(self, client, db):
_ledger_1.ledger = {
"created": "2022/12/01",
"token_name": "テスト原簿",
+ "currency": "JPY",
"headers": [
{
"key": "aaa",
@@ -1468,15 +1493,6 @@ def test_normal_4(self, client, db):
"balance": 30,
"acquisition_date": "2022/12/02",
},
- {
- "account_address": account_address_2,
- "name": "name_test_2",
- "address": "address_test_2",
- "amount": 100,
- "price": 200,
- "balance": 300,
- "acquisition_date": "2022/12/03",
- },
],
"footers": [
{
@@ -1485,43 +1501,7 @@ def test_normal_4(self, client, db):
},
{"f-test1": "a", "f-test2": "b"},
],
- },
- {
- "token_detail_type": "権利_test_2",
- "headers": [
- {
- "key": "aaa",
- "value": "aaa",
- },
- {"test1-1": "a", "test2-1": "b"},
- ],
- "data": [
- {
- "account_address": None,
- "name": "name_test_1",
- "address": "address_test_1",
- "amount": 10,
- "price": 20,
- "balance": 200,
- "acquisition_date": "2020/01/01",
- },
- {
- "account_address": None,
- "name": "name_test_2",
- "address": "address_test_2",
- "amount": 20,
- "price": 30,
- "balance": 600,
- "acquisition_date": "2020/01/02",
- },
- ],
- "footers": [
- {
- "key": "aaa",
- "value": "aaa",
- },
- {"f-test1-1": "a", "f-test2-1": "b"},
- ],
+ "some_personal_info_not_registered": False, # Personal information is set (normally not possible)
},
],
"footers": [
@@ -1540,25 +1520,56 @@ def test_normal_4(self, client, db):
) # JST 2022/01/02
db.add(_ledger_1)
- db.commit()
-
- # request target AsPI
- resp = client.get(
- self.base_url.format(token_address=token_address, ledger_id=1),
- params={
- "latest_flg": 0,
+ _details_1 = LedgerDetailsTemplate()
+ _details_1.token_address = token_address
+ _details_1.token_detail_type = "権利_test_1"
+ _details_1.headers = [
+ {
+ "key": "aaa",
+ "value": "aaa",
},
- headers={
- "issuer-address": issuer_address,
+ {"test1": "a", "test2": "b"},
+ ]
+ _details_1.footers = [
+ {
+ "key": "aaa",
+ "value": "aaa",
},
+ {"f-test1": "a", "f-test2": "b"},
+ ]
+ _details_1.data_type = LedgerDetailsDataType.IBET_FIN.value
+ _details_1.data_source = token_address
+ db.add(_details_1)
+
+ db.commit()
+
+ # Mock
+ token = IbetStraightBondContract()
+ token.personal_info_contract_address = personal_info_contract_address
+ token.issuer_address = issuer_address
+ token.require_personal_info_registered = False
+ token_get_mock = mock.patch(
+ "app.model.blockchain.IbetStraightBondContract.get", return_value=token
)
+ # request target API
+ with token_get_mock as token_get_mock_patch:
+ resp = client.get(
+ self.base_url.format(token_address=token_address, ledger_id=1),
+ params={
+ "latest_flg": 1,
+ },
+ headers={
+ "issuer-address": issuer_address,
+ },
+ )
+
# assertion
assert resp.status_code == 200
assert resp.json() == {
"created": "2022/12/01",
"token_name": "テスト原簿",
- "currency": "",
+ "currency": "JPY",
"headers": [
{
"key": "aaa",
@@ -1582,17 +1593,1245 @@ def test_normal_4(self, client, db):
"data": [
{
"account_address": account_address_1,
- "name": "name_test_1",
- "address": "address_test_1",
+ "name": None, # not null -> null
+ "address": None, # not null -> null
"amount": 10,
"price": 20,
"balance": 30,
"acquisition_date": "2022/12/02",
},
+ ],
+ "footers": [
{
- "account_address": account_address_2,
- "name": "name_test_2",
- "address": "address_test_2",
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"f-test1": "a", "f-test2": "b"},
+ ],
+ "some_personal_info_not_registered": True, # False -> True
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {
+ "f-hoge": "aaaa",
+ "f-fuga": "bbbb",
+ },
+ ],
+ }
+
+ #
+ # latest_flg = 1 (Get the latest personal info)
+ # - address_1 is issuer's address
+ def test_normal_3_4(self, client, db):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ token_address = "0xABCdeF1234567890abcdEf123456789000000000"
+ account_address_1 = "0xABCdeF1234567890abCDeF123456789000000001"
+ personal_info_contract_address = "0xabcDEF1234567890AbcDEf123456789000000003"
+
+ # prepare data
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = ""
+ _token.issuer_address = issuer_address
+ _token.token_address = token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ _ledger_1 = Ledger()
+ _ledger_1.token_address = token_address
+ _ledger_1.token_type = TokenType.IBET_STRAIGHT_BOND.value
+ _ledger_1.ledger = {
+ "created": "2022/12/01",
+ "token_name": "テスト原簿",
+ "currency": "JPY",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {
+ "hoge": "aaaa",
+ "fuga": "bbbb",
+ },
+ ],
+ "details": [
+ {
+ "token_detail_type": "権利_test_1",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"test1": "a", "test2": "b"},
+ ],
+ "data": [
+ {
+ "account_address": issuer_address,
+ "name": "name_test_1",
+ "address": "address_test_1",
+ "amount": 10,
+ "price": 20,
+ "balance": 30,
+ "acquisition_date": "2022/12/02",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"f-test1": "a", "f-test2": "b"},
+ ],
+ "some_personal_info_not_registered": False, # Personal information is set (normally not possible)
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {
+ "f-hoge": "aaaa",
+ "f-fuga": "bbbb",
+ },
+ ],
+ }
+ _ledger_1.ledger_created = datetime.strptime(
+ "2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_ledger_1)
+
+ _details_1 = LedgerDetailsTemplate()
+ _details_1.token_address = token_address
+ _details_1.token_detail_type = "権利_test_1"
+ _details_1.headers = [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"test1": "a", "test2": "b"},
+ ]
+ _details_1.footers = [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"f-test1": "a", "f-test2": "b"},
+ ]
+ _details_1.data_type = LedgerDetailsDataType.IBET_FIN.value
+ _details_1.data_source = token_address
+ db.add(_details_1)
+
+ db.commit()
+
+ # Mock
+ token = IbetStraightBondContract()
+ token.personal_info_contract_address = personal_info_contract_address
+ token.issuer_address = issuer_address
+ token.require_personal_info_registered = False
+ token_get_mock = mock.patch(
+ "app.model.blockchain.IbetStraightBondContract.get", return_value=token
+ )
+
+ # request target API
+ with token_get_mock as token_get_mock_patch:
+ resp = client.get(
+ self.base_url.format(token_address=token_address, ledger_id=1),
+ params={
+ "latest_flg": 1,
+ },
+ headers={
+ "issuer-address": issuer_address,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "created": "2022/12/01",
+ "token_name": "テスト原簿",
+ "currency": "JPY",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {
+ "hoge": "aaaa",
+ "fuga": "bbbb",
+ },
+ ],
+ "details": [
+ {
+ "token_detail_type": "権利_test_1",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"test1": "a", "test2": "b"},
+ ],
+ "data": [
+ {
+ "account_address": issuer_address,
+ "name": None,
+ "address": None,
+ "amount": 10,
+ "price": 20,
+ "balance": 30,
+ "acquisition_date": "2022/12/02",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"f-test1": "a", "f-test2": "b"},
+ ],
+ "some_personal_info_not_registered": False, # Issuer cannot have any personal info
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {
+ "f-hoge": "aaaa",
+ "f-fuga": "bbbb",
+ },
+ ],
+ }
+
+ #
+ # latest_flg = 1 (Get the latest personal info)
+ # - address_1 has personal info in the DB but the values are null
+ # - address_2 has personal info in the DB
+ def test_normal_3_5(self, client, db):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ token_address = "0xABCdeF1234567890abcdEf123456789000000000"
+ account_address_1 = "0xABCdeF1234567890abCDeF123456789000000001"
+ account_address_2 = "0xaBcdEF1234567890aBCDEF123456789000000002"
+ personal_info_contract_address = "0xabcDEF1234567890AbcDEf123456789000000003"
+
+ # prepare data
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = ""
+ _token.issuer_address = issuer_address
+ _token.token_address = token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ _ledger_1 = Ledger()
+ _ledger_1.token_address = token_address
+ _ledger_1.token_type = TokenType.IBET_STRAIGHT_BOND.value
+ _ledger_1.ledger = {
+ "created": "2022/12/01",
+ "token_name": "テスト原簿",
+ "currency": "JPY",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {
+ "hoge": "aaaa",
+ "fuga": "bbbb",
+ },
+ ],
+ "details": [
+ {
+ "token_detail_type": "権利_test_1",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"test1": "a", "test2": "b"},
+ ],
+ "data": [
+ {
+ "account_address": account_address_1,
+ "name": "name_test_1",
+ "address": "address_test_1",
+ "amount": 10,
+ "price": 20,
+ "balance": 30,
+ "acquisition_date": "2022/12/02",
+ },
+ {
+ "account_address": account_address_2,
+ "name": "name_test_2",
+ "address": "address_test_2",
+ "amount": 100,
+ "price": 200,
+ "balance": 300,
+ "acquisition_date": "2022/12/03",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"f-test1": "a", "f-test2": "b"},
+ ],
+ "some_personal_info_not_registered": False,
+ },
+ {
+ "token_detail_type": "権利_test_2",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"test1-1": "a", "test2-1": "b"},
+ ],
+ "data": [
+ {
+ "account_address": None,
+ "name": "name_test_1",
+ "address": "address_test_1",
+ "amount": 10,
+ "price": 20,
+ "balance": 200,
+ "acquisition_date": "2020/01/01",
+ },
+ {
+ "account_address": None,
+ "name": "name_test_2",
+ "address": "address_test_2",
+ "amount": 20,
+ "price": 30,
+ "balance": 600,
+ "acquisition_date": "2020/01/02",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"f-test1-1": "a", "f-test2-1": "b"},
+ ],
+ "some_personal_info_not_registered": False,
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {
+ "f-hoge": "aaaa",
+ "f-fuga": "bbbb",
+ },
+ ],
+ }
+ _ledger_1.ledger_created = datetime.strptime(
+ "2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_ledger_1)
+
+ _idx_personal_info_1 = (
+ IDXPersonalInfo()
+ ) # Note: account_address_1 has personal information in DB but the values are null
+ _idx_personal_info_1.account_address = account_address_1
+ _idx_personal_info_1.issuer_address = issuer_address
+ _idx_personal_info_1.personal_info = {
+ "name": None,
+ "address": None,
+ }
+ db.add(_idx_personal_info_1)
+
+ _idx_personal_info_2 = (
+ IDXPersonalInfo()
+ ) # Note: account_address_2 has personal information in DB
+ _idx_personal_info_2.account_address = account_address_1
+ _idx_personal_info_2.issuer_address = issuer_address
+ _idx_personal_info_2.personal_info = {
+ "name": "name_db_2",
+ "address": "address_db_2",
+ }
+ db.add(_idx_personal_info_1)
+
+ _details_1 = LedgerDetailsTemplate()
+ _details_1.token_address = token_address
+ _details_1.token_detail_type = "権利_test_1"
+ _details_1.headers = [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"test1": "a", "test2": "b"},
+ ]
+ _details_1.footers = [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"f-test1": "a", "f-test2": "b"},
+ ]
+ _details_1.data_type = LedgerDetailsDataType.IBET_FIN.value
+ _details_1.data_source = token_address
+ db.add(_details_1)
+
+ db.commit()
+
+ # Mock
+ token = IbetStraightBondContract()
+ token.personal_info_contract_address = personal_info_contract_address
+ token.issuer_address = issuer_address
+ token.require_personal_info_registered = True
+ token_get_mock = mock.patch(
+ "app.model.blockchain.IbetStraightBondContract.get", return_value=token
+ )
+ personal_get_info_mock = mock.patch(
+ "app.model.blockchain.PersonalInfoContract.get_info"
+ )
+
+ # request target API
+ with token_get_mock as token_get_mock_patch, personal_get_info_mock as personal_get_info_mock_patch:
+ # Note:
+ # account_address_2 has no personal information in the DB
+ # and gets information from the contract
+ personal_get_info_mock_patch.side_effect = [
+ {
+ "name": None,
+ "address": None,
+ },
+ {
+ "name": "name_contract_2",
+ "address": "address_contract_2",
+ },
+ ]
+
+ resp = client.get(
+ self.base_url.format(token_address=token_address, ledger_id=1),
+ params={
+ "latest_flg": 1,
+ },
+ headers={
+ "issuer-address": issuer_address,
+ },
+ )
+ # assertion
+ personal_get_info_mock_patch.assert_has_calls(
+ [call(account_address=account_address_2, default_value=None)]
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "created": "2022/12/01",
+ "token_name": "テスト原簿",
+ "currency": "JPY",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {
+ "hoge": "aaaa",
+ "fuga": "bbbb",
+ },
+ ],
+ "details": [
+ {
+ "token_detail_type": "権利_test_1",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"test1": "a", "test2": "b"},
+ ],
+ "data": [
+ {
+ "account_address": account_address_1,
+ "name": None,
+ "address": None,
+ "amount": 10,
+ "price": 20,
+ "balance": 30,
+ "acquisition_date": "2022/12/02",
+ },
+ {
+ "account_address": account_address_2,
+ "name": "name_contract_2",
+ "address": "address_contract_2",
+ "amount": 100,
+ "price": 200,
+ "balance": 300,
+ "acquisition_date": "2022/12/03",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"f-test1": "a", "f-test2": "b"},
+ ],
+ "some_personal_info_not_registered": True,
+ },
+ {
+ "token_detail_type": "権利_test_2",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"test1-1": "a", "test2-1": "b"},
+ ],
+ "data": [
+ {
+ "account_address": None,
+ "name": "name_test_1",
+ "address": "address_test_1",
+ "amount": 10,
+ "price": 20,
+ "balance": 200,
+ "acquisition_date": "2020/01/01",
+ },
+ {
+ "account_address": None,
+ "name": "name_test_2",
+ "address": "address_test_2",
+ "amount": 20,
+ "price": 30,
+ "balance": 600,
+ "acquisition_date": "2020/01/02",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"f-test1-1": "a", "f-test2-1": "b"},
+ ],
+ "some_personal_info_not_registered": True,
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {
+ "f-hoge": "aaaa",
+ "f-fuga": "bbbb",
+ },
+ ],
+ }
+
+ #
+ # Test `currency` backward compatibility
+ def test_normal_4(self, client, db):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ token_address = "0xABCdeF1234567890abcdEf123456789000000000"
+ account_address_1 = "0xABCdeF1234567890abCDeF123456789000000001"
+ account_address_2 = "0xaBcdEF1234567890aBCDEF123456789000000002"
+
+ # prepare data
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = ""
+ _token.issuer_address = issuer_address
+ _token.token_address = token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ _ledger_1 = Ledger()
+ _ledger_1.token_address = token_address
+ _ledger_1.token_type = TokenType.IBET_STRAIGHT_BOND.value
+ _ledger_1.ledger = {
+ "created": "2022/12/01",
+ "token_name": "テスト原簿",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {
+ "hoge": "aaaa",
+ "fuga": "bbbb",
+ },
+ ],
+ "details": [
+ {
+ "token_detail_type": "権利_test_1",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"test1": "a", "test2": "b"},
+ ],
+ "data": [
+ {
+ "account_address": account_address_1,
+ "name": "name_test_1",
+ "address": "address_test_1",
+ "amount": 10,
+ "price": 20,
+ "balance": 30,
+ "acquisition_date": "2022/12/02",
+ },
+ {
+ "account_address": account_address_2,
+ "name": "name_test_2",
+ "address": "address_test_2",
+ "amount": 100,
+ "price": 200,
+ "balance": 300,
+ "acquisition_date": "2022/12/03",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"f-test1": "a", "f-test2": "b"},
+ ],
+ "some_personal_info_not_registered": False,
+ },
+ {
+ "token_detail_type": "権利_test_2",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"test1-1": "a", "test2-1": "b"},
+ ],
+ "data": [
+ {
+ "account_address": None,
+ "name": "name_test_1",
+ "address": "address_test_1",
+ "amount": 10,
+ "price": 20,
+ "balance": 200,
+ "acquisition_date": "2020/01/01",
+ },
+ {
+ "account_address": None,
+ "name": "name_test_2",
+ "address": "address_test_2",
+ "amount": 20,
+ "price": 30,
+ "balance": 600,
+ "acquisition_date": "2020/01/02",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"f-test1-1": "a", "f-test2-1": "b"},
+ ],
+ "some_personal_info_not_registered": False,
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {
+ "f-hoge": "aaaa",
+ "f-fuga": "bbbb",
+ },
+ ],
+ }
+ _ledger_1.ledger_created = datetime.strptime(
+ "2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_ledger_1)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(token_address=token_address, ledger_id=1),
+ params={
+ "latest_flg": 0,
+ },
+ headers={
+ "issuer-address": issuer_address,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "created": "2022/12/01",
+ "token_name": "テスト原簿",
+ "currency": "",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {
+ "hoge": "aaaa",
+ "fuga": "bbbb",
+ },
+ ],
+ "details": [
+ {
+ "token_detail_type": "権利_test_1",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"test1": "a", "test2": "b"},
+ ],
+ "data": [
+ {
+ "account_address": account_address_1,
+ "name": "name_test_1",
+ "address": "address_test_1",
+ "amount": 10,
+ "price": 20,
+ "balance": 30,
+ "acquisition_date": "2022/12/02",
+ },
+ {
+ "account_address": account_address_2,
+ "name": "name_test_2",
+ "address": "address_test_2",
+ "amount": 100,
+ "price": 200,
+ "balance": 300,
+ "acquisition_date": "2022/12/03",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"f-test1": "a", "f-test2": "b"},
+ ],
+ "some_personal_info_not_registered": False,
+ },
+ {
+ "token_detail_type": "権利_test_2",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"test1-1": "a", "test2-1": "b"},
+ ],
+ "data": [
+ {
+ "account_address": None,
+ "name": "name_test_1",
+ "address": "address_test_1",
+ "amount": 10,
+ "price": 20,
+ "balance": 200,
+ "acquisition_date": "2020/01/01",
+ },
+ {
+ "account_address": None,
+ "name": "name_test_2",
+ "address": "address_test_2",
+ "amount": 20,
+ "price": 30,
+ "balance": 600,
+ "acquisition_date": "2020/01/02",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"f-test1-1": "a", "f-test2-1": "b"},
+ ],
+ "some_personal_info_not_registered": False,
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {
+ "f-hoge": "aaaa",
+ "f-fuga": "bbbb",
+ },
+ ],
+ }
+
+ #
+ # `some_personal_info_not_registered` is not set in ledger data
+ # Test backward compatibility for specifications earlier than v24.6
+ # latest_flg != 1
+ def test_normal_5_1(self, client, db):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ token_address = "0xABCdeF1234567890abcdEf123456789000000000"
+ account_address_1 = "0xABCdeF1234567890abCDeF123456789000000001"
+ account_address_2 = "0xaBcdEF1234567890aBCDEF123456789000000002"
+
+ # prepare data
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = ""
+ _token.issuer_address = issuer_address
+ _token.token_address = token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_23_12
+ db.add(_token)
+
+ _ledger_1 = Ledger()
+ _ledger_1.token_address = token_address
+ _ledger_1.token_type = TokenType.IBET_STRAIGHT_BOND.value
+ _ledger_1.ledger = {
+ "created": "2022/12/01",
+ "token_name": "テスト原簿",
+ "currency": "JPY",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {
+ "hoge": "aaaa",
+ "fuga": "bbbb",
+ },
+ ],
+ "details": [
+ {
+ "token_detail_type": "権利_test_1",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"test1": "a", "test2": "b"},
+ ],
+ "data": [
+ {
+ "account_address": account_address_1,
+ "name": "name_test_1",
+ "address": "address_test_1",
+ "amount": 10,
+ "price": 20,
+ "balance": 30,
+ "acquisition_date": "2022/12/02",
+ },
+ {
+ "account_address": account_address_2,
+ "name": "name_test_2",
+ "address": "address_test_2",
+ "amount": 100,
+ "price": 200,
+ "balance": 300,
+ "acquisition_date": "2022/12/03",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"f-test1": "a", "f-test2": "b"},
+ ],
+ },
+ {
+ "token_detail_type": "権利_test_2",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"test1-1": "a", "test2-1": "b"},
+ ],
+ "data": [
+ {
+ "account_address": None,
+ "name": "name_test_1",
+ "address": "address_test_1",
+ "amount": 10,
+ "price": 20,
+ "balance": 200,
+ "acquisition_date": "2020/01/01",
+ },
+ {
+ "account_address": None,
+ "name": "name_test_2",
+ "address": "address_test_2",
+ "amount": 20,
+ "price": 30,
+ "balance": 600,
+ "acquisition_date": "2020/01/02",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"f-test1-1": "a", "f-test2-1": "b"},
+ ],
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {
+ "f-hoge": "aaaa",
+ "f-fuga": "bbbb",
+ },
+ ],
+ }
+ _ledger_1.ledger_created = datetime.strptime(
+ "2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_ledger_1)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(token_address=token_address, ledger_id=1),
+ params={
+ "latest_flg": 0,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "created": "2022/12/01",
+ "token_name": "テスト原簿",
+ "currency": "JPY",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {
+ "hoge": "aaaa",
+ "fuga": "bbbb",
+ },
+ ],
+ "details": [
+ {
+ "token_detail_type": "権利_test_1",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"test1": "a", "test2": "b"},
+ ],
+ "data": [
+ {
+ "account_address": account_address_1,
+ "name": "name_test_1",
+ "address": "address_test_1",
+ "amount": 10,
+ "price": 20,
+ "balance": 30,
+ "acquisition_date": "2022/12/02",
+ },
+ {
+ "account_address": account_address_2,
+ "name": "name_test_2",
+ "address": "address_test_2",
+ "amount": 100,
+ "price": 200,
+ "balance": 300,
+ "acquisition_date": "2022/12/03",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"f-test1": "a", "f-test2": "b"},
+ ],
+ "some_personal_info_not_registered": False,
+ },
+ {
+ "token_detail_type": "権利_test_2",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"test1-1": "a", "test2-1": "b"},
+ ],
+ "data": [
+ {
+ "account_address": None,
+ "name": "name_test_1",
+ "address": "address_test_1",
+ "amount": 10,
+ "price": 20,
+ "balance": 200,
+ "acquisition_date": "2020/01/01",
+ },
+ {
+ "account_address": None,
+ "name": "name_test_2",
+ "address": "address_test_2",
+ "amount": 20,
+ "price": 30,
+ "balance": 600,
+ "acquisition_date": "2020/01/02",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"f-test1-1": "a", "f-test2-1": "b"},
+ ],
+ "some_personal_info_not_registered": False,
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {
+ "f-hoge": "aaaa",
+ "f-fuga": "bbbb",
+ },
+ ],
+ }
+
+ #
+ # `some_personal_info_not_registered` is not set in ledger data
+ # Test backward compatibility for specifications earlier than v24.6
+ # latest_flg == 1
+ def test_normal_5_2(self, client, db):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ token_address = "0xABCdeF1234567890abcdEf123456789000000000"
+ account_address_1 = "0xABCdeF1234567890abCDeF123456789000000001"
+ account_address_2 = "0xaBcdEF1234567890aBCDEF123456789000000002"
+ personal_info_contract_address = "0xabcDEF1234567890AbcDEf123456789000000003"
+
+ # prepare data
+ _token = Token()
+ _token.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token.tx_hash = ""
+ _token.issuer_address = issuer_address
+ _token.token_address = token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_23_12
+ db.add(_token)
+
+ _ledger_1 = Ledger()
+ _ledger_1.token_address = token_address
+ _ledger_1.token_type = TokenType.IBET_STRAIGHT_BOND.value
+ _ledger_1.ledger = {
+ "created": "2022/12/01",
+ "token_name": "テスト原簿",
+ "currency": "JPY",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {
+ "hoge": "aaaa",
+ "fuga": "bbbb",
+ },
+ ],
+ "details": [
+ {
+ "token_detail_type": "権利_test_1",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"test1": "a", "test2": "b"},
+ ],
+ "data": [
+ {
+ "account_address": account_address_1,
+ "name": "name_test_1",
+ "address": "address_test_1",
+ "amount": 10,
+ "price": 20,
+ "balance": 30,
+ "acquisition_date": "2022/12/02",
+ },
+ {
+ "account_address": account_address_2,
+ "name": "name_test_2",
+ "address": "address_test_2",
+ "amount": 100,
+ "price": 200,
+ "balance": 300,
+ "acquisition_date": "2022/12/03",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"f-test1": "a", "f-test2": "b"},
+ ],
+ },
+ {
+ "token_detail_type": "権利_test_2",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"test1-1": "a", "test2-1": "b"},
+ ],
+ "data": [
+ {
+ "account_address": None,
+ "name": "name_test_1",
+ "address": "address_test_1",
+ "amount": 10,
+ "price": 20,
+ "balance": 200,
+ "acquisition_date": "2020/01/01",
+ },
+ {
+ "account_address": None,
+ "name": "name_test_2",
+ "address": "address_test_2",
+ "amount": 20,
+ "price": 30,
+ "balance": 600,
+ "acquisition_date": "2020/01/02",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"f-test1-1": "a", "f-test2-1": "b"},
+ ],
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {
+ "f-hoge": "aaaa",
+ "f-fuga": "bbbb",
+ },
+ ],
+ }
+ _ledger_1.ledger_created = datetime.strptime(
+ "2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_ledger_1)
+
+ _idx_personal_info_1 = (
+ IDXPersonalInfo()
+ ) # Note: account_address_1 has personal information in DB
+ _idx_personal_info_1.account_address = account_address_1
+ _idx_personal_info_1.issuer_address = issuer_address
+ _idx_personal_info_1.personal_info = {
+ "name": "name_db_1",
+ "address": "address_db_1",
+ }
+ db.add(_idx_personal_info_1)
+
+ db.commit()
+
+ # Mock
+ token = IbetStraightBondContract()
+ token.personal_info_contract_address = personal_info_contract_address
+ token.issuer_address = issuer_address
+ token.require_personal_info_registered = False
+ token_get_mock = mock.patch(
+ "app.model.blockchain.IbetStraightBondContract.get", return_value=token
+ )
+
+ # request target API
+ with token_get_mock:
+ resp = client.get(
+ self.base_url.format(token_address=token_address, ledger_id=1),
+ params={
+ "latest_flg": 1,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "created": "2022/12/01",
+ "token_name": "テスト原簿",
+ "currency": "JPY",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {
+ "hoge": "aaaa",
+ "fuga": "bbbb",
+ },
+ ],
+ "details": [
+ {
+ "token_detail_type": "権利_test_1",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "aaa",
+ },
+ {"test1": "a", "test2": "b"},
+ ],
+ "data": [
+ {
+ "account_address": account_address_1,
+ "name": "name_test_1",
+ "address": "address_test_1",
+ "amount": 10,
+ "price": 20,
+ "balance": 30,
+ "acquisition_date": "2022/12/02",
+ },
+ {
+ "account_address": account_address_2,
+ "name": "name_test_2",
+ "address": "address_test_2",
"amount": 100,
"price": 200,
"balance": 300,
@@ -1606,6 +2845,7 @@ def test_normal_4(self, client, db):
},
{"f-test1": "a", "f-test2": "b"},
],
+ "some_personal_info_not_registered": False,
},
{
"token_detail_type": "権利_test_2",
@@ -1643,6 +2883,7 @@ def test_normal_4(self, client, db):
},
{"f-test1-1": "a", "f-test2-1": "b"},
],
+ "some_personal_info_not_registered": False,
},
],
"footers": [
@@ -1775,7 +3016,7 @@ def test_error_4_1(self, client, db):
_token.token_address = token_address
_token.abi = {}
_token.token_status = 2
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -1834,7 +3075,7 @@ def test_error_5(self, client, db):
_token.token_address = token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -1871,7 +3112,7 @@ def test_error_6(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -1910,7 +3151,7 @@ def test_error_7(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_ledger_1 = Ledger()
@@ -1986,7 +3227,7 @@ def test_error_7(self, client, db):
db.commit()
- # request target AsPI
+ # request target API
with mock.patch("app.utils.fastapi_utils.RESPONSE_VALIDATION_MODE", False):
resp = client.get(
self.base_url.format(token_address=token_address, ledger_id=1),
diff --git a/tests/test_app_routers_ledger_{token_address}_template_DELETE.py b/tests/app/test_ledger_{token_address}_template_DELETE.py
similarity index 98%
rename from tests/test_app_routers_ledger_{token_address}_template_DELETE.py
rename to tests/app/test_ledger_{token_address}_template_DELETE.py
index 3be30149..94206ff1 100644
--- a/tests/test_app_routers_ledger_{token_address}_template_DELETE.py
+++ b/tests/app/test_ledger_{token_address}_template_DELETE.py
@@ -51,7 +51,7 @@ def test_normal_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_template = LedgerTemplate()
@@ -232,7 +232,7 @@ def test_error_4(self, client, db):
_token.token_address = token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -266,7 +266,7 @@ def test_error_5(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
diff --git a/tests/test_app_routers_ledger_{token_address}_template_GET.py b/tests/app/test_ledger_{token_address}_template_GET.py
similarity index 98%
rename from tests/test_app_routers_ledger_{token_address}_template_GET.py
rename to tests/app/test_ledger_{token_address}_template_GET.py
index f1e9c9d4..de480c29 100644
--- a/tests/test_app_routers_ledger_{token_address}_template_GET.py
+++ b/tests/app/test_ledger_{token_address}_template_GET.py
@@ -50,7 +50,7 @@ def test_normal_1_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_template = LedgerTemplate()
@@ -215,7 +215,7 @@ def test_normal_1_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_template = LedgerTemplate()
@@ -377,7 +377,7 @@ def test_normal_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_template = LedgerTemplate()
@@ -475,7 +475,7 @@ def test_error_2(self, client, db):
_token.token_address = token_address
_token.abi = {}
_token.token_status = 2
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -528,7 +528,7 @@ def test_error_3(self, client, db):
_token.token_address = token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -562,7 +562,7 @@ def test_error_4(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
diff --git a/tests/test_app_routers_ledger_{token_address}_template_POST.py b/tests/app/test_ledger_{token_address}_template_POST.py
similarity index 99%
rename from tests/test_app_routers_ledger_{token_address}_template_POST.py
rename to tests/app/test_ledger_{token_address}_template_POST.py
index 52a1de1f..4b1f64ba 100644
--- a/tests/test_app_routers_ledger_{token_address}_template_POST.py
+++ b/tests/app/test_ledger_{token_address}_template_POST.py
@@ -55,7 +55,7 @@ def test_normal_1(self, mock_func, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -247,7 +247,7 @@ def test_normal_2(self, mock_func, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_template = LedgerTemplate()
@@ -906,7 +906,7 @@ def test_error_6(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -1097,7 +1097,7 @@ def test_error_8(self, client, db):
_token.token_address = token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
diff --git a/tests/test_app_routers_notifications_GET.py b/tests/app/test_notifications_GET.py
similarity index 100%
rename from tests/test_app_routers_notifications_GET.py
rename to tests/app/test_notifications_GET.py
diff --git a/tests/test_app_routers_notifications_{notice_id}_DELETE.py b/tests/app/test_notifications_{notice_id}_DELETE.py
similarity index 100%
rename from tests/test_app_routers_notifications_{notice_id}_DELETE.py
rename to tests/app/test_notifications_{notice_id}_DELETE.py
diff --git a/tests/test_app_routers_positions_{account_address}_GET.py b/tests/app/test_positions_{account_address}_GET.py
similarity index 97%
rename from tests/test_app_routers_positions_{account_address}_GET.py
rename to tests/app/test_positions_{account_address}_GET.py
index 726610f8..243844a0 100644
--- a/tests/test_app_routers_positions_{account_address}_GET.py
+++ b/tests/app/test_positions_{account_address}_GET.py
@@ -43,7 +43,7 @@ def test_normal_1(self, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -93,7 +93,7 @@ def test_normal_2(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -188,7 +188,7 @@ def test_normal_3_1(
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position 1
@@ -227,7 +227,7 @@ def test_normal_3_1(
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position-2
@@ -266,7 +266,7 @@ def test_normal_3_1(
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position-3
@@ -381,7 +381,7 @@ def test_normal_3_2(
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position 1
@@ -401,7 +401,7 @@ def test_normal_3_2(
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position 2
@@ -431,7 +431,7 @@ def test_normal_3_2(
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position 3
@@ -522,7 +522,7 @@ def test_normal_4(
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -544,7 +544,7 @@ def test_normal_4(
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -564,7 +564,7 @@ def test_normal_4(
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -645,7 +645,7 @@ def test_normal_5_1(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -665,7 +665,7 @@ def test_normal_5_1(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -685,7 +685,7 @@ def test_normal_5_1(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -763,7 +763,7 @@ def test_normal_5_2(self, mock_IbetShareContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -783,7 +783,7 @@ def test_normal_5_2(self, mock_IbetShareContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -803,7 +803,7 @@ def test_normal_5_2(self, mock_IbetShareContract_get, client, db):
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -870,7 +870,7 @@ def test_normal_5_3(
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -890,7 +890,7 @@ def test_normal_5_3(
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -910,7 +910,7 @@ def test_normal_5_3(
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -930,7 +930,7 @@ def test_normal_5_3(
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -1036,7 +1036,7 @@ def test_normal_6(
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -1056,7 +1056,7 @@ def test_normal_6(
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -1076,7 +1076,7 @@ def test_normal_6(
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -1096,7 +1096,7 @@ def test_normal_6(
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
diff --git a/tests/test_app_routers_positions_{account_address}_forceunlock_POST.py b/tests/app/test_positions_{account_address}_forceunlock_POST.py
similarity index 98%
rename from tests/test_app_routers_positions_{account_address}_forceunlock_POST.py
rename to tests/app/test_positions_{account_address}_forceunlock_POST.py
index a52c727c..43850152 100644
--- a/tests/test_app_routers_positions_{account_address}_forceunlock_POST.py
+++ b/tests/app/test_positions_{account_address}_forceunlock_POST.py
@@ -64,7 +64,7 @@ def test_normal_1(self, IbetSecurityTokenInterface_mock, client, db):
token.issuer_address = _admin_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -140,7 +140,7 @@ def test_normal_2(self, IbetSecurityTokenInterface_mock, client, db):
token.issuer_address = _admin_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -522,7 +522,7 @@ def test_error_3_1(self, client, db):
token.issuer_address = _admin_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -626,7 +626,7 @@ def test_error_3_3(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -685,7 +685,7 @@ def test_error_4(self, client, db):
token.issuer_address = _admin_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -744,7 +744,7 @@ def test_error_5(self, client, db):
token.issuer_address = _admin_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_positions_{account_address}_lock_GET.py b/tests/app/test_positions_{account_address}_lock_GET.py
similarity index 97%
rename from tests/test_app_routers_positions_{account_address}_lock_GET.py
rename to tests/app/test_positions_{account_address}_lock_GET.py
index 5359cad0..3f08808b 100644
--- a/tests/test_app_routers_positions_{account_address}_lock_GET.py
+++ b/tests/app/test_positions_{account_address}_lock_GET.py
@@ -43,7 +43,7 @@ def test_normal_1(self, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -87,7 +87,7 @@ def test_normal_2_1(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_token = Token()
@@ -96,7 +96,7 @@ def test_normal_2_1(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Locked Position
@@ -186,7 +186,7 @@ def test_normal_2_2(self, mock_IbetShareContract_get, client, db):
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_token = Token()
@@ -195,7 +195,7 @@ def test_normal_2_2(self, mock_IbetShareContract_get, client, db):
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Locked Position
@@ -279,7 +279,7 @@ def test_normal_3_1(self, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Locked Position
@@ -332,7 +332,7 @@ def test_normal_3_2(self, mock_IbetStraightBondContract_get, client, db):
_token.tx_hash = ""
_token.abi = ""
_token.token_status = 2
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_token = Token()
@@ -341,7 +341,7 @@ def test_normal_3_2(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Locked Position
@@ -414,7 +414,7 @@ def test_normal_4(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_token = Token()
@@ -423,7 +423,7 @@ def test_normal_4(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Locked Position
@@ -498,7 +498,7 @@ def test_normal_5(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_token = Token()
@@ -507,7 +507,7 @@ def test_normal_5(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Locked Position
@@ -580,7 +580,7 @@ def test_normal_6(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Locked Position
diff --git a/tests/test_app_routers_positions_{account_address}_lock_events_GET.py b/tests/app/test_positions_{account_address}_lock_events_GET.py
similarity index 94%
rename from tests/test_app_routers_positions_{account_address}_lock_events_GET.py
rename to tests/app/test_positions_{account_address}_lock_events_GET.py
index a05a0b4d..3f51494c 100644
--- a/tests/test_app_routers_positions_{account_address}_lock_events_GET.py
+++ b/tests/app/test_positions_{account_address}_lock_events_GET.py
@@ -17,7 +17,7 @@
SPDX-License-Identifier: Apache-2.0
"""
-from datetime import datetime
+from datetime import UTC, datetime
from unittest import mock
from unittest.mock import ANY
@@ -45,7 +45,7 @@ def test_normal_1(self, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -88,7 +88,7 @@ def test_normal_2_1(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Lock events
@@ -101,7 +101,7 @@ def test_normal_2_1(self, mock_IbetStraightBondContract_get, client, db):
_lock.account_address = account_address
_lock.value = 1
_lock.data = {"message": "locked_1"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
_unlock = IDXUnlock()
@@ -114,7 +114,7 @@ def test_normal_2_1(self, mock_IbetStraightBondContract_get, client, db):
_unlock.recipient_address = other_account_address
_unlock.value = 1
_unlock.data = {"message": "unlocked_1"}
- _unlock.block_timestamp = datetime.utcnow()
+ _unlock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_unlock)
db.commit()
@@ -188,7 +188,7 @@ def test_normal_2_2(self, mock_IbetShareContract_get, client, db):
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Lock events
@@ -201,7 +201,7 @@ def test_normal_2_2(self, mock_IbetShareContract_get, client, db):
_lock.account_address = account_address
_lock.value = 1
_lock.data = {"message": "locked_1"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
_unlock = IDXUnlock()
@@ -214,7 +214,7 @@ def test_normal_2_2(self, mock_IbetShareContract_get, client, db):
_unlock.recipient_address = other_account_address
_unlock.value = 1
_unlock.data = {"message": "unlocked_1"}
- _unlock.block_timestamp = datetime.utcnow()
+ _unlock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_unlock)
db.commit()
@@ -289,7 +289,7 @@ def test_normal_3_1(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Lock events
@@ -302,7 +302,7 @@ def test_normal_3_1(self, mock_IbetStraightBondContract_get, client, db):
_lock.account_address = other_account_address # others
_lock.value = 1
_lock.data = {"message": "locked_1"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
_unlock = IDXUnlock()
@@ -315,7 +315,7 @@ def test_normal_3_1(self, mock_IbetStraightBondContract_get, client, db):
_unlock.recipient_address = other_account_address
_unlock.value = 1
_unlock.data = {"message": "unlocked_1"}
- _unlock.block_timestamp = datetime.utcnow()
+ _unlock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_unlock)
db.commit()
@@ -360,7 +360,7 @@ def test_normal_3_2(self, mock_IbetStraightBondContract_get, client, db):
_token.tx_hash = ""
_token.abi = ""
_token.token_status = 2
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Lock events
@@ -373,7 +373,7 @@ def test_normal_3_2(self, mock_IbetStraightBondContract_get, client, db):
_lock.account_address = account_address
_lock.value = 1
_lock.data = {"message": "locked_1"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
_unlock = IDXUnlock()
@@ -386,7 +386,7 @@ def test_normal_3_2(self, mock_IbetStraightBondContract_get, client, db):
_unlock.recipient_address = other_account_address
_unlock.value = 1
_unlock.data = {"message": "unlocked_1"}
- _unlock.block_timestamp = datetime.utcnow()
+ _unlock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_unlock)
db.commit()
@@ -431,7 +431,7 @@ def test_normal_4(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_token = Token()
@@ -440,7 +440,7 @@ def test_normal_4(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Lock events
@@ -453,7 +453,7 @@ def test_normal_4(self, mock_IbetStraightBondContract_get, client, db):
_lock.account_address = account_address
_lock.value = 1
_lock.data = {"message": "locked_1"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
_unlock = IDXUnlock()
@@ -466,7 +466,7 @@ def test_normal_4(self, mock_IbetStraightBondContract_get, client, db):
_unlock.recipient_address = other_account_address
_unlock.value = 1
_unlock.data = {"message": "unlocked_1"}
- _unlock.block_timestamp = datetime.utcnow()
+ _unlock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_unlock)
_lock = IDXLock()
@@ -478,7 +478,7 @@ def test_normal_4(self, mock_IbetStraightBondContract_get, client, db):
_lock.account_address = account_address
_lock.value = 1
_lock.data = {"message": "locked_1"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
_unlock = IDXUnlock()
@@ -491,7 +491,7 @@ def test_normal_4(self, mock_IbetStraightBondContract_get, client, db):
_unlock.recipient_address = other_account_address
_unlock.value = 1
_unlock.data = {"message": "unlocked_1"}
- _unlock.block_timestamp = datetime.utcnow()
+ _unlock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_unlock)
db.commit()
@@ -566,7 +566,7 @@ def test_normal_5_1(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Lock events
@@ -579,7 +579,7 @@ def test_normal_5_1(self, mock_IbetStraightBondContract_get, client, db):
_lock.account_address = account_address
_lock.value = 1
_lock.data = {"message": "locked_1"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
_unlock = IDXUnlock()
@@ -592,7 +592,7 @@ def test_normal_5_1(self, mock_IbetStraightBondContract_get, client, db):
_unlock.recipient_address = other_account_address
_unlock.value = 1
_unlock.data = {"message": "unlocked_1"}
- _unlock.block_timestamp = datetime.utcnow()
+ _unlock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_unlock)
db.commit()
@@ -653,7 +653,7 @@ def test_normal_5_2(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_token = Token()
@@ -662,7 +662,7 @@ def test_normal_5_2(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Lock events
@@ -675,7 +675,7 @@ def test_normal_5_2(self, mock_IbetStraightBondContract_get, client, db):
_lock.account_address = account_address
_lock.value = 1
_lock.data = {"message": "locked_1"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
_unlock = IDXUnlock()
@@ -688,7 +688,7 @@ def test_normal_5_2(self, mock_IbetStraightBondContract_get, client, db):
_unlock.recipient_address = other_account_address
_unlock.value = 1
_unlock.data = {"message": "unlocked_1"}
- _unlock.block_timestamp = datetime.utcnow()
+ _unlock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_unlock)
db.commit()
@@ -749,7 +749,7 @@ def test_normal_5_3(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value # bond
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_token = Token()
@@ -758,7 +758,7 @@ def test_normal_5_3(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_SHARE.value # share
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Lock events
@@ -771,7 +771,7 @@ def test_normal_5_3(self, mock_IbetStraightBondContract_get, client, db):
_lock.account_address = account_address
_lock.value = 1
_lock.data = {"message": "locked_1"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
_unlock = IDXUnlock()
@@ -784,7 +784,7 @@ def test_normal_5_3(self, mock_IbetStraightBondContract_get, client, db):
_unlock.recipient_address = other_account_address
_unlock.value = 1
_unlock.data = {"message": "unlocked_1"}
- _unlock.block_timestamp = datetime.utcnow()
+ _unlock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_unlock)
db.commit()
@@ -844,7 +844,7 @@ def test_normal_5_4(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value # bond
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Lock events
@@ -858,7 +858,7 @@ def test_normal_5_4(self, mock_IbetStraightBondContract_get, client, db):
_lock.recipient_address = lock_address_1
_lock.value = 1
_lock.data = {"message": "unlocked_1"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
_lock = IDXLock()
@@ -871,7 +871,7 @@ def test_normal_5_4(self, mock_IbetStraightBondContract_get, client, db):
_lock.recipient_address = lock_address_2
_lock.value = 1
_lock.data = {"message": "unlocked_2"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
db.commit()
@@ -931,7 +931,7 @@ def test_normal_5_5(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value # bond
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Lock events
@@ -944,7 +944,7 @@ def test_normal_5_5(self, mock_IbetStraightBondContract_get, client, db):
_lock.account_address = account_address
_lock.value = 1
_lock.data = {"message": "locked_1"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
_lock = IDXLock()
@@ -956,7 +956,7 @@ def test_normal_5_5(self, mock_IbetStraightBondContract_get, client, db):
_lock.account_address = account_address
_lock.value = 1
_lock.data = {"message": "locked_2"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
db.commit()
@@ -1017,7 +1017,7 @@ def test_normal_5_6(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value # bond
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Lock events
@@ -1031,7 +1031,7 @@ def test_normal_5_6(self, mock_IbetStraightBondContract_get, client, db):
_unlock.recipient_address = other_account_address_1
_unlock.value = 1
_unlock.data = {"message": "unlocked_1"}
- _unlock.block_timestamp = datetime.utcnow()
+ _unlock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_unlock)
_unlock = IDXUnlock()
@@ -1044,7 +1044,7 @@ def test_normal_5_6(self, mock_IbetStraightBondContract_get, client, db):
_unlock.recipient_address = other_account_address_2
_unlock.value = 1
_unlock.data = {"message": "unlocked_2"}
- _unlock.block_timestamp = datetime.utcnow()
+ _unlock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_unlock)
db.commit()
@@ -1104,7 +1104,7 @@ def test_normal_6(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Lock events
@@ -1117,7 +1117,7 @@ def test_normal_6(self, mock_IbetStraightBondContract_get, client, db):
_lock.account_address = account_address
_lock.value = 1
_lock.data = {"message": "locked_1"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
_lock = IDXLock()
@@ -1129,7 +1129,7 @@ def test_normal_6(self, mock_IbetStraightBondContract_get, client, db):
_lock.account_address = account_address
_lock.value = 1
_lock.data = {"message": "locked_2"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
_lock = IDXLock()
@@ -1141,7 +1141,7 @@ def test_normal_6(self, mock_IbetStraightBondContract_get, client, db):
_lock.account_address = account_address
_lock.value = 1
_lock.data = {"message": "locked_3"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
_lock = IDXLock()
@@ -1153,7 +1153,7 @@ def test_normal_6(self, mock_IbetStraightBondContract_get, client, db):
_lock.account_address = account_address
_lock.value = 1
_lock.data = {"message": "locked_4"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
db.commit()
@@ -1257,7 +1257,7 @@ def test_normal_7(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Lock events
@@ -1270,7 +1270,7 @@ def test_normal_7(self, mock_IbetStraightBondContract_get, client, db):
_lock.account_address = account_address
_lock.value = 1
_lock.data = {"message": "locked_1"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
_lock = IDXLock()
@@ -1282,7 +1282,7 @@ def test_normal_7(self, mock_IbetStraightBondContract_get, client, db):
_lock.account_address = account_address
_lock.value = 1
_lock.data = {"message": "locked_2"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
_lock = IDXLock()
@@ -1294,7 +1294,7 @@ def test_normal_7(self, mock_IbetStraightBondContract_get, client, db):
_lock.account_address = account_address
_lock.value = 1
_lock.data = {"message": "locked_3"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
db.commit()
diff --git a/tests/test_app_routers_positions_{account_address}_{token_address}_GET.py b/tests/app/test_positions_{account_address}_{token_address}_GET.py
similarity index 98%
rename from tests/test_app_routers_positions_{account_address}_{token_address}_GET.py
rename to tests/app/test_positions_{account_address}_{token_address}_GET.py
index 15f93c4a..82da5a01 100644
--- a/tests/test_app_routers_positions_{account_address}_{token_address}_GET.py
+++ b/tests/app/test_positions_{account_address}_{token_address}_GET.py
@@ -48,7 +48,7 @@ def test_normal_1_1(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -133,7 +133,7 @@ def test_normal_1_2(self, mock_IbetShareContract_get, client, db):
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -216,7 +216,7 @@ def test_normal_2(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -273,7 +273,7 @@ def test_normal_3_1(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Locked Position
@@ -330,7 +330,7 @@ def test_normal_3_2(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -398,7 +398,7 @@ def test_normal_3_3(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -455,7 +455,7 @@ def test_normal_3_4(self, mock_IbetStraightBondContract_get, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -578,7 +578,7 @@ def test_error_2_2(self, client, db):
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
@@ -623,7 +623,7 @@ def test_error_3(self, client, db):
_token.tx_hash = ""
_token.abi = ""
_token.token_status = 0
- _token.version = TokenVersion.V_23_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Position
diff --git a/tests/app/test_settlement_dvp_agent_account_{account_address}_DELETE.py b/tests/app/test_settlement_dvp_agent_account_{account_address}_DELETE.py
new file mode 100644
index 00000000..1c2aef7b
--- /dev/null
+++ b/tests/app/test_settlement_dvp_agent_account_{account_address}_DELETE.py
@@ -0,0 +1,79 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+from sqlalchemy import select
+
+from app.model.db import DVPAgentAccount
+
+
+class TestDeleteDVPAgentAccount:
+ # Target API endpoint
+ base_url = "/settlement/dvp/agent/account/{account_address}"
+
+ ###########################################################################
+ # Normal Case
+ ###########################################################################
+
+ #
+ def test_normal_1(self, client, db):
+ test_account_address = "0x1234567890123456789012345678900000000000"
+
+ # Prepare data
+ dvp_agent_account = DVPAgentAccount()
+ dvp_agent_account.account_address = test_account_address
+ dvp_agent_account.keyfile = "test_keyfile_0"
+ dvp_agent_account.eoa_password = "test_password_0"
+ db.add(dvp_agent_account)
+
+ db.commit()
+
+ # Request target api
+ resp = client.delete(self.base_url.format(account_address=test_account_address))
+
+ # Assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "account_address": "0x1234567890123456789012345678900000000000",
+ "is_deleted": True,
+ }
+
+ dvp_agent_account_af = db.scalars(
+ select(DVPAgentAccount)
+ .where(DVPAgentAccount.account_address == test_account_address)
+ .limit(1)
+ ).first()
+ assert dvp_agent_account_af.is_deleted is True
+
+ ###########################################################################
+ # Error Case
+ ###########################################################################
+
+ #
+ def test_error_1(self, client, db):
+ test_account_address = "0x1234567890123456789012345678900000000000"
+
+ # Request target api
+ resp = client.delete(self.base_url.format(account_address=test_account_address))
+
+ # Assertion
+ assert resp.status_code == 404
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "NotFound"},
+ "detail": "account is not exists",
+ }
diff --git a/tests/app/test_settlement_dvp_agent_account_{account_address}_eoa_password_POST.py b/tests/app/test_settlement_dvp_agent_account_{account_address}_eoa_password_POST.py
new file mode 100644
index 00000000..2696c166
--- /dev/null
+++ b/tests/app/test_settlement_dvp_agent_account_{account_address}_eoa_password_POST.py
@@ -0,0 +1,204 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+from sqlalchemy import select
+
+from app.model.db import DVPAgentAccount
+from app.utils.e2ee_utils import E2EEUtils
+from tests.account_config import config_eth_account
+
+
+class TestChangeDVPAgentAccountPassword:
+ # Target API endpoint
+ base_url = "/settlement/dvp/agent/account/{account_address}/eoa_password"
+
+ ###########################################################################
+ # Normal Case
+ ###########################################################################
+
+ #
+ def test_normal_1(self, client, db):
+ user_1 = config_eth_account("user1")
+ user_address_1 = user_1["address"]
+ user_keyfile_1 = user_1["keyfile_json"]
+ old_password = "password"
+ new_password = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 *+.\\()?[]^$-|!#%&\"',/:;<=>@_`{}~"
+
+ # Prepare data
+ dvp_agent_account = DVPAgentAccount()
+ dvp_agent_account.account_address = user_address_1
+ dvp_agent_account.keyfile = user_keyfile_1
+ dvp_agent_account.eoa_password = E2EEUtils.encrypt(old_password)
+ db.add(dvp_agent_account)
+
+ db.commit()
+
+ # Request target api
+ req_param = {
+ "old_eoa_password": E2EEUtils.encrypt(old_password),
+ "eoa_password": E2EEUtils.encrypt(new_password),
+ }
+ resp = client.post(
+ self.base_url.format(account_address=user_address_1), json=req_param
+ )
+
+ # Assertion
+ assert resp.status_code == 200
+
+ dvp_agent_account_af = db.scalars(
+ select(DVPAgentAccount)
+ .where(DVPAgentAccount.account_address == user_address_1)
+ .limit(1)
+ ).first()
+ assert E2EEUtils.decrypt(dvp_agent_account_af.eoa_password) == new_password
+
+ ###########################################################################
+ # Error Case
+ ###########################################################################
+
+ #
+ # Missing required fields
+ # -> RequestValidationError
+ def test_error_1(self, client, db):
+ user_1 = config_eth_account("user1")
+ user_address_1 = user_1["address"]
+
+ # Request target api
+ req_param = {}
+ resp = client.post(
+ self.base_url.format(account_address=user_address_1), json=req_param
+ )
+
+ # Assertion
+ assert resp.status_code == 422
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "type": "missing",
+ "loc": ["body", "old_eoa_password"],
+ "msg": "Field required",
+ "input": {},
+ },
+ {
+ "type": "missing",
+ "loc": ["body", "eoa_password"],
+ "msg": "Field required",
+ "input": {},
+ },
+ ],
+ }
+
+ #
+ # Password is not encrypted
+ # -> RequestValidationError
+ def test_error_2(self, client, db):
+ user_1 = config_eth_account("user1")
+ user_address_1 = user_1["address"]
+
+ # Request target api
+ req_param = {
+ "old_eoa_password": "raw_password",
+ "eoa_password": "raw_password",
+ }
+ resp = client.post(
+ self.base_url.format(account_address=user_address_1), json=req_param
+ )
+
+ # Assertion
+ assert resp.status_code == 422
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "type": "value_error",
+ "loc": ["body", "old_eoa_password"],
+ "msg": "Value error, old_eoa_password is not a Base64-encoded encrypted data",
+ "input": "raw_password",
+ "ctx": {"error": {}},
+ },
+ {
+ "type": "value_error",
+ "loc": ["body", "eoa_password"],
+ "msg": "Value error, eoa_password is not a Base64-encoded encrypted data",
+ "input": "raw_password",
+ "ctx": {"error": {}},
+ },
+ ],
+ }
+
+ #
+ # Log account is not exists
+ # -> NotFound
+ def test_error_3(self, client, db):
+ user_1 = config_eth_account("user1")
+ user_address_1 = user_1["address"]
+ old_password = "password"
+ new_password = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 *+.\\()?[]^$-|!#%&\"',/:;<=>@_`{}~"
+
+ # Request target api
+ req_param = {
+ "old_eoa_password": E2EEUtils.encrypt(old_password),
+ "eoa_password": E2EEUtils.encrypt(new_password),
+ }
+ resp = client.post(
+ self.base_url.format(account_address=user_address_1), json=req_param
+ )
+
+ # Assertion
+ assert resp.status_code == 404
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "NotFound"},
+ "detail": "account is not exists",
+ }
+
+ #
+ # New password violates password policy
+ # -> InvalidParameterError
+ def test_error_4(self, client, db):
+ user_1 = config_eth_account("user1")
+ user_address_1 = user_1["address"]
+ user_keyfile_1 = user_1["keyfile_json"]
+ old_password = "password"
+ new_password = "password🚀"
+
+ # Prepare data
+ dvp_agent_account = DVPAgentAccount()
+ dvp_agent_account.account_address = user_address_1
+ dvp_agent_account.keyfile = user_keyfile_1
+ dvp_agent_account.eoa_password = E2EEUtils.encrypt(old_password)
+ db.add(dvp_agent_account)
+
+ db.commit()
+
+ # Request target api
+ req_param = {
+ "old_eoa_password": E2EEUtils.encrypt(old_password),
+ "eoa_password": E2EEUtils.encrypt(new_password),
+ }
+ resp = client.post(
+ self.base_url.format(account_address=user_address_1), json=req_param
+ )
+
+ # Assertion
+ assert resp.status_code == 400
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "InvalidParameterError"},
+ "detail": "password must be 8 to 200 alphanumeric or symbolic character",
+ }
diff --git a/tests/app/test_settlement_dvp_agent_accounts_GET.py b/tests/app/test_settlement_dvp_agent_accounts_GET.py
new file mode 100644
index 00000000..58a9f5d3
--- /dev/null
+++ b/tests/app/test_settlement_dvp_agent_accounts_GET.py
@@ -0,0 +1,73 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+from app.model.db import DVPAgentAccount
+
+
+class TestListAllDVPAgentAccounts:
+ # Target API endpoint
+ test_url = "/settlement/dvp/agent/accounts"
+
+ ###########################################################################
+ # Normal Case
+ ###########################################################################
+
+ #
+ # Data does not exist
+ def test_normal_1(self, client, db):
+ # Request target api
+ resp = client.get(self.test_url)
+
+ # Assertion
+ assert resp.status_code == 200
+ assert resp.json() == []
+
+ #
+ # Data exist
+ def test_normal_2(self, client, db):
+ # Prepare data
+ dvp_agent_account = DVPAgentAccount()
+ dvp_agent_account.account_address = "0x1234567890123456789012345678900000000000"
+ dvp_agent_account.keyfile = "test_keyfile_0"
+ dvp_agent_account.eoa_password = "test_password_0"
+ db.add(dvp_agent_account)
+
+ dvp_agent_account = DVPAgentAccount()
+ dvp_agent_account.account_address = "0x1234567890123456789012345678900000000001"
+ dvp_agent_account.keyfile = "test_keyfile_1"
+ dvp_agent_account.eoa_password = "test_password_1"
+ db.add(dvp_agent_account)
+
+ db.commit()
+
+ # Request target api
+ resp = client.get(self.test_url)
+
+ # Assertion
+ assert resp.status_code == 200
+ assert resp.json() == [
+ {
+ "account_address": "0x1234567890123456789012345678900000000000",
+ "is_deleted": False,
+ },
+ {
+ "account_address": "0x1234567890123456789012345678900000000001",
+ "is_deleted": False,
+ },
+ ]
diff --git a/tests/app/test_settlement_dvp_agent_accounts_POST.py b/tests/app/test_settlement_dvp_agent_accounts_POST.py
new file mode 100644
index 00000000..5892c1a3
--- /dev/null
+++ b/tests/app/test_settlement_dvp_agent_accounts_POST.py
@@ -0,0 +1,170 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+import base64
+from unittest import mock
+
+from sqlalchemy import select
+
+from app.model.db import DVPAgentAccount, TransactionLock
+from app.utils.e2ee_utils import E2EEUtils
+from config import EOA_PASSWORD_PATTERN_MSG
+
+
+class TestCreateDVPAgentAccount:
+ # Target API endpoint
+ test_url = "/settlement/dvp/agent/accounts"
+
+ valid_password = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 *+.\\()?[]^$-|!#%&\"',/:;<=>@_`{}~"
+ invalid_password = "password🚀"
+
+ ###########################################################################
+ # Normal Case
+ ###########################################################################
+
+ #
+ # Use Linux RNG
+ def test_normal_1(self, client, db, ibet_security_token_dvp_contract):
+ # Request target api
+ req_param = {"eoa_password": E2EEUtils.encrypt(self.valid_password)}
+ resp = client.post(self.test_url, json=req_param)
+
+ # Assertion
+ dvp_agent_account = db.scalars(select(DVPAgentAccount).limit(1)).first()
+ assert dvp_agent_account is not None
+
+ tx_lock = db.scalars(
+ select(TransactionLock)
+ .where(TransactionLock.tx_from == dvp_agent_account.account_address)
+ .limit(1)
+ ).first()
+ assert tx_lock is not None
+
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "account_address": dvp_agent_account.account_address,
+ "is_deleted": dvp_agent_account.is_deleted,
+ }
+
+ #
+ # Use AWS RNG
+ def test_normal_2(self, client, db, ibet_security_token_dvp_contract):
+ # Mock setting
+ class KMSClientMock:
+ def generate_random(self, NumberOfBytes):
+ assert NumberOfBytes == 32
+ return {"Plaintext": b"12345678901234567890123456789012"}
+
+ mock_boto3_client = mock.patch(
+ target="boto3.client", side_effect=[KMSClientMock()]
+ )
+
+ # Request target api
+ with mock.patch(
+ "app.routers.settlement.AWS_KMS_GENERATE_RANDOM_ENABLED", True
+ ), mock_boto3_client:
+ req_param = {"eoa_password": E2EEUtils.encrypt(self.valid_password)}
+ resp = client.post(self.test_url, json=req_param)
+
+ # Assertion
+ dvp_agent_account = db.scalars(select(DVPAgentAccount).limit(1)).first()
+ assert dvp_agent_account is not None
+
+ tx_lock = db.scalars(
+ select(TransactionLock)
+ .where(TransactionLock.tx_from == dvp_agent_account.account_address)
+ .limit(1)
+ ).first()
+ assert tx_lock is not None
+
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "account_address": dvp_agent_account.account_address,
+ "is_deleted": dvp_agent_account.is_deleted,
+ }
+
+ ###########################################################################
+ # Error Case
+ ###########################################################################
+
+ #
+ # Parameter Error
+ # Missing required field
+ # -> RequestValidationError
+ def test_error_1(self, client, db, ibet_security_token_dvp_contract):
+ # Request target api
+ req_param = {}
+ resp = client.post(self.test_url, json=req_param)
+
+ # Assertion
+ assert resp.status_code == 422
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "type": "missing",
+ "loc": ["body", "eoa_password"],
+ "msg": "Field required",
+ "input": {},
+ }
+ ],
+ }
+
+ #
+ # Parameter Error
+ # Not encrypted password
+ # -> RequestValidationError
+ def test_error_2(self, client, db, ibet_security_token_dvp_contract):
+ # Request target api
+ req_param = {
+ "eoa_password": base64.encodebytes(
+ "password".encode("utf-8")
+ ).decode(), # Not encrypted
+ }
+ resp = client.post(self.test_url, json=req_param)
+
+ # Assertion
+ assert resp.status_code == 422
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "type": "value_error",
+ "loc": ["body", "eoa_password"],
+ "msg": "Value error, eoa_password is not a Base64-encoded encrypted data",
+ "input": "cGFzc3dvcmQ=\n",
+ "ctx": {"error": {}},
+ }
+ ],
+ }
+
+ #
+ # Password policy violation
+ # -> InvalidParameterError
+ def test_error_3(self, client, db, ibet_security_token_dvp_contract):
+ # Request target api
+ req_param = {"eoa_password": E2EEUtils.encrypt(self.invalid_password)}
+ resp = client.post(self.test_url, json=req_param)
+
+ # Assertion
+ assert resp.status_code == 400
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "InvalidParameterError"},
+ "detail": EOA_PASSWORD_PATTERN_MSG,
+ }
diff --git a/tests/app/test_settlement_dvp_{exchange_address}_deliveries_GET.py b/tests/app/test_settlement_dvp_{exchange_address}_deliveries_GET.py
new file mode 100644
index 00000000..b41a05a0
--- /dev/null
+++ b/tests/app/test_settlement_dvp_{exchange_address}_deliveries_GET.py
@@ -0,0 +1,2548 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+from datetime import UTC, datetime
+
+import pytz
+
+from app.model.db import DeliveryStatus, IDXDelivery
+
+
+class TestListAllDVPDeliveries:
+ # target API endpoint
+ base_url = "/settlement/dvp/{exchange_address}/deliveries"
+
+ ###########################################################################
+ # Normal Case
+ ###########################################################################
+
+ # Normal_1
+ # 0 record
+ def test_normal_1(self, client, db):
+ exchange_address = "0x1234567890123456789012345678900000000000"
+
+ # request target api
+ resp = client.get(
+ self.base_url.format(exchange_address=exchange_address),
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {
+ "count": 0,
+ "offset": None,
+ "limit": None,
+ "total": 0,
+ },
+ "deliveries": [],
+ }
+
+ # Normal_2
+ # Multi record
+ def test_normal_2(self, client, db):
+ exchange_address = "0x1234567890123456789012345678900000000000"
+ token_address_1 = "0x1234567890123456789012345678900000000010"
+ token_address_2 = "0x1234567890123456789012345678900000000020"
+
+ seller_address_1 = "0x1234567890123456789012345678900000000100"
+ seller_address_2 = "0x1234567890123456789012345678900000000200"
+
+ buyer_address = "0x1234567890123456789012345678911111111111"
+
+ agent_address_1 = "0x1234567890123456789012345678900000001000"
+ agent_address_2 = "0x1234567890123456789012345678900000002000"
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 1
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Canceled)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 2
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.cancel_blocktimestamp = datetime(2024, 1, 1, 0, 0, 1, tzinfo=UTC)
+ _idx_delivery.cancel_transaction_hash = "tx_hash_2"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CANCELED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Confirmed)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 3
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CONFIRMED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Finished)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 4
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = datetime(2024, 1, 1, 0, 0, 3, tzinfo=UTC)
+ _idx_delivery.finish_transaction_hash = "tx_hash_4"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_FINISHED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Aborted)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 5
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = None
+ _idx_delivery.finish_transaction_hash = None
+ _idx_delivery.abort_blocktimestamp = datetime(2024, 1, 1, 0, 0, 4, tzinfo=UTC)
+ _idx_delivery.abort_transaction_hash = "tx_hash_5"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_ABORTED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 6
+ _idx_delivery.token_address = token_address_2
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_2
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_2
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+ db.commit()
+
+ # request target api
+ resp = client.get(
+ self.base_url.format(exchange_address=exchange_address),
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 6, "limit": None, "offset": None, "total": 6},
+ "deliveries": [
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 1,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": None,
+ "confirm_transaction_hash": None,
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": False,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_CREATED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 2,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": "2023-12-31T15:00:01+00:00",
+ "cancel_transaction_hash": "tx_hash_2",
+ "confirm_blocktimestamp": None,
+ "confirm_transaction_hash": None,
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": False,
+ "valid": False,
+ "status": DeliveryStatus.DELIVERY_CANCELED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 3,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": "2023-12-31T15:00:02+00:00",
+ "confirm_transaction_hash": "tx_hash_3",
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": True,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_CONFIRMED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 4,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": "2023-12-31T15:00:02+00:00",
+ "confirm_transaction_hash": "tx_hash_3",
+ "finish_blocktimestamp": "2023-12-31T15:00:03+00:00",
+ "finish_transaction_hash": "tx_hash_4",
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": True,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_FINISHED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 5,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": "2023-12-31T15:00:02+00:00",
+ "confirm_transaction_hash": "tx_hash_3",
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": "2023-12-31T15:00:04+00:00",
+ "abort_transaction_hash": "tx_hash_5",
+ "confirmed": True,
+ "valid": False,
+ "status": DeliveryStatus.DELIVERY_ABORTED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 6,
+ "token_address": token_address_2,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_2,
+ "amount": 1,
+ "agent_address": agent_address_2,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": None,
+ "confirm_transaction_hash": None,
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": False,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_CREATED,
+ },
+ ],
+ }
+
+ # Normal_3_1
+ # Search filter: token_address
+ def test_normal_3_1(self, client, db):
+ exchange_address = "0x1234567890123456789012345678900000000000"
+ token_address_1 = "0x1234567890123456789012345678900000000010"
+ token_address_2 = "0x1234567890123456789012345678900000000020"
+
+ seller_address_1 = "0x1234567890123456789012345678900000000100"
+ seller_address_2 = "0x1234567890123456789012345678900000000200"
+
+ buyer_address = "0x1234567890123456789012345678911111111111"
+
+ agent_address_1 = "0x1234567890123456789012345678900000001000"
+ agent_address_2 = "0x1234567890123456789012345678900000002000"
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 1
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Canceled)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 2
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.cancel_blocktimestamp = datetime(2024, 1, 1, 0, 0, 1, tzinfo=UTC)
+ _idx_delivery.cancel_transaction_hash = "tx_hash_2"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CANCELED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Confirmed)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 3
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CONFIRMED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Finished)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 4
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = datetime(2024, 1, 1, 0, 0, 3, tzinfo=UTC)
+ _idx_delivery.finish_transaction_hash = "tx_hash_4"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_FINISHED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Aborted)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 5
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = None
+ _idx_delivery.finish_transaction_hash = None
+ _idx_delivery.abort_blocktimestamp = datetime(2024, 1, 1, 0, 0, 4, tzinfo=UTC)
+ _idx_delivery.abort_transaction_hash = "tx_hash_5"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_ABORTED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 6
+ _idx_delivery.token_address = token_address_2
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_2
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_2
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+ db.commit()
+
+ # request target api
+ resp = client.get(
+ self.base_url.format(exchange_address=exchange_address),
+ params={"token_address": token_address_1},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 5, "limit": None, "offset": None, "total": 6},
+ "deliveries": [
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 1,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": None,
+ "confirm_transaction_hash": None,
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": False,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_CREATED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 2,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": "2023-12-31T15:00:01+00:00",
+ "cancel_transaction_hash": "tx_hash_2",
+ "confirm_blocktimestamp": None,
+ "confirm_transaction_hash": None,
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": False,
+ "valid": False,
+ "status": DeliveryStatus.DELIVERY_CANCELED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 3,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": "2023-12-31T15:00:02+00:00",
+ "confirm_transaction_hash": "tx_hash_3",
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": True,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_CONFIRMED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 4,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": "2023-12-31T15:00:02+00:00",
+ "confirm_transaction_hash": "tx_hash_3",
+ "finish_blocktimestamp": "2023-12-31T15:00:03+00:00",
+ "finish_transaction_hash": "tx_hash_4",
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": True,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_FINISHED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 5,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": "2023-12-31T15:00:02+00:00",
+ "confirm_transaction_hash": "tx_hash_3",
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": "2023-12-31T15:00:04+00:00",
+ "abort_transaction_hash": "tx_hash_5",
+ "confirmed": True,
+ "valid": False,
+ "status": DeliveryStatus.DELIVERY_ABORTED,
+ },
+ ],
+ }
+
+ # Normal_3_2
+ # Search filter: seller_address
+ def test_normal_3_2(self, client, db):
+ exchange_address = "0x1234567890123456789012345678900000000000"
+ token_address_1 = "0x1234567890123456789012345678900000000010"
+ token_address_2 = "0x1234567890123456789012345678900000000020"
+
+ seller_address_1 = "0x1234567890123456789012345678900000000100"
+ seller_address_2 = "0x1234567890123456789012345678900000000200"
+
+ buyer_address = "0x1234567890123456789012345678911111111111"
+
+ agent_address_1 = "0x1234567890123456789012345678900000001000"
+ agent_address_2 = "0x1234567890123456789012345678900000002000"
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 1
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Canceled)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 2
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.cancel_blocktimestamp = datetime(2024, 1, 1, 0, 0, 1, tzinfo=UTC)
+ _idx_delivery.cancel_transaction_hash = "tx_hash_2"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CANCELED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Confirmed)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 3
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CONFIRMED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Finished)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 4
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = datetime(2024, 1, 1, 0, 0, 3, tzinfo=UTC)
+ _idx_delivery.finish_transaction_hash = "tx_hash_4"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_FINISHED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Aborted)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 5
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = None
+ _idx_delivery.finish_transaction_hash = None
+ _idx_delivery.abort_blocktimestamp = datetime(2024, 1, 1, 0, 0, 4, tzinfo=UTC)
+ _idx_delivery.abort_transaction_hash = "tx_hash_5"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_ABORTED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 6
+ _idx_delivery.token_address = token_address_2
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_2
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_2
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 2, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+ db.commit()
+
+ # request target api
+ resp = client.get(
+ self.base_url.format(exchange_address=exchange_address),
+ params={"seller_address": seller_address_1},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 5, "limit": None, "offset": None, "total": 6},
+ "deliveries": [
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 1,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": None,
+ "confirm_transaction_hash": None,
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": False,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_CREATED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 2,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": "2023-12-31T15:00:01+00:00",
+ "cancel_transaction_hash": "tx_hash_2",
+ "confirm_blocktimestamp": None,
+ "confirm_transaction_hash": None,
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": False,
+ "valid": False,
+ "status": DeliveryStatus.DELIVERY_CANCELED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 3,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": "2023-12-31T15:00:02+00:00",
+ "confirm_transaction_hash": "tx_hash_3",
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": True,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_CONFIRMED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 4,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": "2023-12-31T15:00:02+00:00",
+ "confirm_transaction_hash": "tx_hash_3",
+ "finish_blocktimestamp": "2023-12-31T15:00:03+00:00",
+ "finish_transaction_hash": "tx_hash_4",
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": True,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_FINISHED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 5,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": "2023-12-31T15:00:02+00:00",
+ "confirm_transaction_hash": "tx_hash_3",
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": "2023-12-31T15:00:04+00:00",
+ "abort_transaction_hash": "tx_hash_5",
+ "confirmed": True,
+ "valid": False,
+ "status": DeliveryStatus.DELIVERY_ABORTED,
+ },
+ ],
+ }
+
+ # Normal_3_3
+ # Search filter: agent_address
+ def test_normal_3_3(self, client, db):
+ exchange_address = "0x1234567890123456789012345678900000000000"
+ token_address_1 = "0x1234567890123456789012345678900000000010"
+ token_address_2 = "0x1234567890123456789012345678900000000020"
+
+ seller_address_1 = "0x1234567890123456789012345678900000000100"
+ seller_address_2 = "0x1234567890123456789012345678900000000200"
+
+ buyer_address = "0x1234567890123456789012345678911111111111"
+
+ agent_address_1 = "0x1234567890123456789012345678900000001000"
+ agent_address_2 = "0x1234567890123456789012345678900000002000"
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 1
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Canceled)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 2
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.cancel_blocktimestamp = datetime(2024, 1, 1, 0, 0, 1, tzinfo=UTC)
+ _idx_delivery.cancel_transaction_hash = "tx_hash_2"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CANCELED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Confirmed)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 3
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CONFIRMED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Finished)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 4
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = datetime(2024, 1, 1, 0, 0, 3, tzinfo=UTC)
+ _idx_delivery.finish_transaction_hash = "tx_hash_4"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_FINISHED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Aborted)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 5
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = None
+ _idx_delivery.finish_transaction_hash = None
+ _idx_delivery.abort_blocktimestamp = datetime(2024, 1, 1, 0, 0, 4, tzinfo=UTC)
+ _idx_delivery.abort_transaction_hash = "tx_hash_5"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_ABORTED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 6
+ _idx_delivery.token_address = token_address_2
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_2
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_2
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 2, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+ db.commit()
+
+ # request target api
+ resp = client.get(
+ self.base_url.format(exchange_address=exchange_address),
+ params={"agent_address": agent_address_1},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 5, "limit": None, "offset": None, "total": 6},
+ "deliveries": [
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 1,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": None,
+ "confirm_transaction_hash": None,
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": False,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_CREATED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 2,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": "2023-12-31T15:00:01+00:00",
+ "cancel_transaction_hash": "tx_hash_2",
+ "confirm_blocktimestamp": None,
+ "confirm_transaction_hash": None,
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": False,
+ "valid": False,
+ "status": DeliveryStatus.DELIVERY_CANCELED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 3,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": "2023-12-31T15:00:02+00:00",
+ "confirm_transaction_hash": "tx_hash_3",
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": True,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_CONFIRMED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 4,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": "2023-12-31T15:00:02+00:00",
+ "confirm_transaction_hash": "tx_hash_3",
+ "finish_blocktimestamp": "2023-12-31T15:00:03+00:00",
+ "finish_transaction_hash": "tx_hash_4",
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": True,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_FINISHED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 5,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": "2023-12-31T15:00:02+00:00",
+ "confirm_transaction_hash": "tx_hash_3",
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": "2023-12-31T15:00:04+00:00",
+ "abort_transaction_hash": "tx_hash_5",
+ "confirmed": True,
+ "valid": False,
+ "status": DeliveryStatus.DELIVERY_ABORTED,
+ },
+ ],
+ }
+
+ # Normal_3_4
+ # Search filter: valid
+ def test_normal_3_4(self, client, db):
+ exchange_address = "0x1234567890123456789012345678900000000000"
+ token_address_1 = "0x1234567890123456789012345678900000000010"
+ token_address_2 = "0x1234567890123456789012345678900000000020"
+
+ seller_address_1 = "0x1234567890123456789012345678900000000100"
+ seller_address_2 = "0x1234567890123456789012345678900000000200"
+
+ buyer_address = "0x1234567890123456789012345678911111111111"
+
+ agent_address_1 = "0x1234567890123456789012345678900000001000"
+ agent_address_2 = "0x1234567890123456789012345678900000002000"
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 1
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Canceled)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 2
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.cancel_blocktimestamp = datetime(2024, 1, 1, 0, 0, 1, tzinfo=UTC)
+ _idx_delivery.cancel_transaction_hash = "tx_hash_2"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CANCELED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Confirmed)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 3
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CONFIRMED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Finished)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 4
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = datetime(2024, 1, 1, 0, 0, 3, tzinfo=UTC)
+ _idx_delivery.finish_transaction_hash = "tx_hash_4"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_FINISHED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Aborted)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 5
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = None
+ _idx_delivery.finish_transaction_hash = None
+ _idx_delivery.abort_blocktimestamp = datetime(2024, 1, 1, 0, 0, 4, tzinfo=UTC)
+ _idx_delivery.abort_transaction_hash = "tx_hash_5"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_ABORTED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 6
+ _idx_delivery.token_address = token_address_2
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_2
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_2
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 2, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+ db.commit()
+
+ # request target api
+ resp = client.get(
+ self.base_url.format(exchange_address=exchange_address),
+ params={"valid": False},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 2, "limit": None, "offset": None, "total": 6},
+ "deliveries": [
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 2,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": "2023-12-31T15:00:01+00:00",
+ "cancel_transaction_hash": "tx_hash_2",
+ "confirm_blocktimestamp": None,
+ "confirm_transaction_hash": None,
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": False,
+ "valid": False,
+ "status": DeliveryStatus.DELIVERY_CANCELED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 5,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": "2023-12-31T15:00:02+00:00",
+ "confirm_transaction_hash": "tx_hash_3",
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": "2023-12-31T15:00:04+00:00",
+ "abort_transaction_hash": "tx_hash_5",
+ "confirmed": True,
+ "valid": False,
+ "status": DeliveryStatus.DELIVERY_ABORTED,
+ },
+ ],
+ }
+
+ # Normal_3_5
+ # Search filter: status
+ def test_normal_3_5(self, client, db):
+ exchange_address = "0x1234567890123456789012345678900000000000"
+ token_address_1 = "0x1234567890123456789012345678900000000010"
+ token_address_2 = "0x1234567890123456789012345678900000000020"
+
+ seller_address_1 = "0x1234567890123456789012345678900000000100"
+ seller_address_2 = "0x1234567890123456789012345678900000000200"
+
+ buyer_address = "0x1234567890123456789012345678911111111111"
+
+ agent_address_1 = "0x1234567890123456789012345678900000001000"
+ agent_address_2 = "0x1234567890123456789012345678900000002000"
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 1
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Canceled)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 2
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.cancel_blocktimestamp = datetime(2024, 1, 1, 0, 0, 1, tzinfo=UTC)
+ _idx_delivery.cancel_transaction_hash = "tx_hash_2"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CANCELED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Confirmed)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 3
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CONFIRMED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Finished)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 4
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = datetime(2024, 1, 1, 0, 0, 3, tzinfo=UTC)
+ _idx_delivery.finish_transaction_hash = "tx_hash_4"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_FINISHED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Aborted)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 5
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = None
+ _idx_delivery.finish_transaction_hash = None
+ _idx_delivery.abort_blocktimestamp = datetime(2024, 1, 1, 0, 0, 4, tzinfo=UTC)
+ _idx_delivery.abort_transaction_hash = "tx_hash_5"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_ABORTED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 6
+ _idx_delivery.token_address = token_address_2
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_2
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_2
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 2, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+ db.commit()
+
+ # request target api
+ resp = client.get(
+ self.base_url.format(exchange_address=exchange_address),
+ params={"status": DeliveryStatus.DELIVERY_FINISHED.value},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 1, "limit": None, "offset": None, "total": 6},
+ "deliveries": [
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 4,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": "2023-12-31T15:00:02+00:00",
+ "confirm_transaction_hash": "tx_hash_3",
+ "finish_blocktimestamp": "2023-12-31T15:00:03+00:00",
+ "finish_transaction_hash": "tx_hash_4",
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": True,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_FINISHED,
+ },
+ ],
+ }
+
+ # Normal_3_6_1
+ # Search filter: create_blocktimestamp_from
+ def test_normal_3_6_1(self, client, db):
+ exchange_address = "0x1234567890123456789012345678900000000000"
+ token_address_1 = "0x1234567890123456789012345678900000000010"
+ token_address_2 = "0x1234567890123456789012345678900000000020"
+
+ seller_address_1 = "0x1234567890123456789012345678900000000100"
+ seller_address_2 = "0x1234567890123456789012345678900000000200"
+
+ buyer_address = "0x1234567890123456789012345678911111111111"
+
+ agent_address_1 = "0x1234567890123456789012345678900000001000"
+ agent_address_2 = "0x1234567890123456789012345678900000002000"
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 1
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 1, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Canceled)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 2
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.cancel_blocktimestamp = datetime(2024, 1, 1, 0, 0, 1, tzinfo=UTC)
+ _idx_delivery.cancel_transaction_hash = "tx_hash_2"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CANCELED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Confirmed)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 3
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CONFIRMED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Finished)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 4
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = datetime(2024, 1, 1, 0, 0, 3, tzinfo=UTC)
+ _idx_delivery.finish_transaction_hash = "tx_hash_4"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_FINISHED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Aborted)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 5
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = None
+ _idx_delivery.finish_transaction_hash = None
+ _idx_delivery.abort_blocktimestamp = datetime(2024, 1, 1, 0, 0, 4, tzinfo=UTC)
+ _idx_delivery.abort_transaction_hash = "tx_hash_5"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_ABORTED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 6
+ _idx_delivery.token_address = token_address_2
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_2
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_2
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+ db.commit()
+
+ # request target api
+ resp = client.get(
+ self.base_url.format(exchange_address=exchange_address),
+ params={"create_blocktimestamp_from": str(datetime(2024, 1, 1, 9, 0, 1))},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 1, "limit": None, "offset": None, "total": 6},
+ "deliveries": [
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 1,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:01+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": None,
+ "confirm_transaction_hash": None,
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": False,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_CREATED,
+ },
+ ],
+ }
+
+ # Normal_3_6_2
+ # Search filter: create_blocktimestamp_to
+ def test_normal_3_6_2(self, client, db):
+ exchange_address = "0x1234567890123456789012345678900000000000"
+ token_address_1 = "0x1234567890123456789012345678900000000010"
+ token_address_2 = "0x1234567890123456789012345678900000000020"
+
+ seller_address_1 = "0x1234567890123456789012345678900000000100"
+ seller_address_2 = "0x1234567890123456789012345678900000000200"
+
+ buyer_address = "0x1234567890123456789012345678911111111111"
+
+ agent_address_1 = "0x1234567890123456789012345678900000001000"
+ agent_address_2 = "0x1234567890123456789012345678900000002000"
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 1
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Canceled)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 2
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 1, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.cancel_blocktimestamp = datetime(2024, 1, 1, 0, 0, 1, tzinfo=UTC)
+ _idx_delivery.cancel_transaction_hash = "tx_hash_2"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CANCELED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Confirmed)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 3
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CONFIRMED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Finished)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 4
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 3, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 3, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = datetime(2024, 1, 1, 0, 0, 3, tzinfo=UTC)
+ _idx_delivery.finish_transaction_hash = "tx_hash_4"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_FINISHED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Aborted)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 5
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 4, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 4, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = None
+ _idx_delivery.finish_transaction_hash = None
+ _idx_delivery.abort_blocktimestamp = datetime(2024, 1, 1, 0, 0, 4, tzinfo=UTC)
+ _idx_delivery.abort_transaction_hash = "tx_hash_5"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_ABORTED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 6
+ _idx_delivery.token_address = token_address_2
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_2
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_2
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 2, 0, 0, 5)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+ db.commit()
+
+ # request target api
+ resp = client.get(
+ self.base_url.format(exchange_address=exchange_address),
+ params={"create_blocktimestamp_to": str(datetime(2024, 1, 1, 9, 0, 1))},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 2, "limit": None, "offset": None, "total": 6},
+ "deliveries": [
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 2,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:01+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": "2023-12-31T15:00:01+00:00",
+ "cancel_transaction_hash": "tx_hash_2",
+ "confirm_blocktimestamp": None,
+ "confirm_transaction_hash": None,
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": False,
+ "valid": False,
+ "status": DeliveryStatus.DELIVERY_CANCELED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 1,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": None,
+ "confirm_transaction_hash": None,
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": False,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_CREATED,
+ },
+ ],
+ }
+
+ # Normal_3_6_3
+ # Search filter: create_blocktimestamp_from & create_blocktimestamp_to
+ def test_normal_3_6_3(self, client, db):
+ exchange_address = "0x1234567890123456789012345678900000000000"
+ token_address_1 = "0x1234567890123456789012345678900000000010"
+ token_address_2 = "0x1234567890123456789012345678900000000020"
+
+ seller_address_1 = "0x1234567890123456789012345678900000000100"
+ seller_address_2 = "0x1234567890123456789012345678900000000200"
+
+ buyer_address = "0x1234567890123456789012345678911111111111"
+
+ agent_address_1 = "0x1234567890123456789012345678900000001000"
+ agent_address_2 = "0x1234567890123456789012345678900000002000"
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 1
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Canceled)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 2
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 1, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.cancel_blocktimestamp = datetime(2024, 1, 1, 0, 0, 1, tzinfo=UTC)
+ _idx_delivery.cancel_transaction_hash = "tx_hash_2"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CANCELED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Confirmed)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 3
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CONFIRMED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Finished)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 4
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 3, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 3, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = datetime(2024, 1, 1, 0, 0, 3, tzinfo=UTC)
+ _idx_delivery.finish_transaction_hash = "tx_hash_4"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_FINISHED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Aborted)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 5
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 4, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 4, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = None
+ _idx_delivery.finish_transaction_hash = None
+ _idx_delivery.abort_blocktimestamp = datetime(2024, 1, 1, 0, 0, 4, tzinfo=UTC)
+ _idx_delivery.abort_transaction_hash = "tx_hash_5"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_ABORTED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 6
+ _idx_delivery.token_address = token_address_2
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_2
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_2
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 2, 0, 0, 5)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+ db.commit()
+
+ # request target api
+ resp = client.get(
+ self.base_url.format(exchange_address=exchange_address),
+ params={
+ "create_blocktimestamp_from": str(datetime(2024, 1, 1, 9, 0, 1)),
+ "create_blocktimestamp_to": str(datetime(2024, 1, 1, 9, 0, 1)),
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 1, "limit": None, "offset": None, "total": 6},
+ "deliveries": [
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 2,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:01+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": "2023-12-31T15:00:01+00:00",
+ "cancel_transaction_hash": "tx_hash_2",
+ "confirm_blocktimestamp": None,
+ "confirm_transaction_hash": None,
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": False,
+ "valid": False,
+ "status": DeliveryStatus.DELIVERY_CANCELED,
+ },
+ ],
+ }
+
+ # Normal_4
+ # Sort
+ def test_normal_4(self, client, db):
+ exchange_address = "0x1234567890123456789012345678900000000000"
+ token_address_1 = "0x1234567890123456789012345678900000000010"
+ token_address_2 = "0x1234567890123456789012345678900000000020"
+
+ seller_address_1 = "0x1234567890123456789012345678900000000100"
+ seller_address_2 = "0x1234567890123456789012345678900000000200"
+
+ buyer_address = "0x1234567890123456789012345678911111111111"
+
+ agent_address_1 = "0x1234567890123456789012345678900000001000"
+ agent_address_2 = "0x1234567890123456789012345678900000002000"
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 1
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Canceled)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 2
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 1, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.cancel_blocktimestamp = datetime(2024, 1, 1, 0, 0, 1, tzinfo=UTC)
+ _idx_delivery.cancel_transaction_hash = "tx_hash_2"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CANCELED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Confirmed)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 3
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CONFIRMED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Finished)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 4
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 3, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 3, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = datetime(2024, 1, 1, 0, 0, 3, tzinfo=UTC)
+ _idx_delivery.finish_transaction_hash = "tx_hash_4"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_FINISHED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Aborted)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 5
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 4, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 4, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = None
+ _idx_delivery.finish_transaction_hash = None
+ _idx_delivery.abort_blocktimestamp = datetime(2024, 1, 1, 0, 0, 4, tzinfo=UTC)
+ _idx_delivery.abort_transaction_hash = "tx_hash_5"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_ABORTED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 6
+ _idx_delivery.token_address = token_address_2
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_2
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_2
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 2, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+ db.commit()
+
+ # request target api
+ resp = client.get(
+ self.base_url.format(exchange_address=exchange_address),
+ params={"sort_order": 0},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 6, "limit": None, "offset": None, "total": 6},
+ "deliveries": [
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 1,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": None,
+ "confirm_transaction_hash": None,
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": False,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_CREATED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 2,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:01+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": "2023-12-31T15:00:01+00:00",
+ "cancel_transaction_hash": "tx_hash_2",
+ "confirm_blocktimestamp": None,
+ "confirm_transaction_hash": None,
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": False,
+ "valid": False,
+ "status": DeliveryStatus.DELIVERY_CANCELED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 3,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:02+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": "2023-12-31T15:00:02+00:00",
+ "confirm_transaction_hash": "tx_hash_3",
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": True,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_CONFIRMED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 4,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:03+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": "2023-12-31T15:00:03+00:00",
+ "confirm_transaction_hash": "tx_hash_3",
+ "finish_blocktimestamp": "2023-12-31T15:00:03+00:00",
+ "finish_transaction_hash": "tx_hash_4",
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": True,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_FINISHED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 5,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:04+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": "2023-12-31T15:00:04+00:00",
+ "confirm_transaction_hash": "tx_hash_3",
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": "2023-12-31T15:00:04+00:00",
+ "abort_transaction_hash": "tx_hash_5",
+ "confirmed": True,
+ "valid": False,
+ "status": DeliveryStatus.DELIVERY_ABORTED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 6,
+ "token_address": token_address_2,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_2,
+ "amount": 1,
+ "agent_address": agent_address_2,
+ "data": "",
+ "create_blocktimestamp": "2024-01-01T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": None,
+ "confirm_transaction_hash": None,
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": False,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_CREATED,
+ },
+ ],
+ }
+
+ # Normal_5
+ # Pagination
+ def test_normal_5(self, client, db):
+ exchange_address = "0x1234567890123456789012345678900000000000"
+ token_address_1 = "0x1234567890123456789012345678900000000010"
+ token_address_2 = "0x1234567890123456789012345678900000000020"
+
+ seller_address_1 = "0x1234567890123456789012345678900000000100"
+ seller_address_2 = "0x1234567890123456789012345678900000000200"
+
+ buyer_address = "0x1234567890123456789012345678911111111111"
+
+ agent_address_1 = "0x1234567890123456789012345678900000001000"
+ agent_address_2 = "0x1234567890123456789012345678900000002000"
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 1
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Canceled)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 2
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.cancel_blocktimestamp = datetime(2024, 1, 1, 0, 0, 1, tzinfo=UTC)
+ _idx_delivery.cancel_transaction_hash = "tx_hash_2"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CANCELED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Confirmed)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 3
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CONFIRMED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Finished)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 4
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = datetime(2024, 1, 1, 0, 0, 3, tzinfo=UTC)
+ _idx_delivery.finish_transaction_hash = "tx_hash_4"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_FINISHED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Aborted)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 5
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirm_blocktimestamp = datetime(2024, 1, 1, 0, 0, 2, tzinfo=UTC)
+ _idx_delivery.confirm_transaction_hash = "tx_hash_3"
+ _idx_delivery.finish_blocktimestamp = None
+ _idx_delivery.finish_transaction_hash = None
+ _idx_delivery.abort_blocktimestamp = datetime(2024, 1, 1, 0, 0, 4, tzinfo=UTC)
+ _idx_delivery.abort_transaction_hash = "tx_hash_5"
+ _idx_delivery.confirmed = True
+ _idx_delivery.valid = False
+ _idx_delivery.status = DeliveryStatus.DELIVERY_ABORTED.value
+ db.add(_idx_delivery)
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 6
+ _idx_delivery.token_address = token_address_2
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_2
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_2
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 2, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+ db.commit()
+
+ # request target api
+ resp = client.get(
+ self.base_url.format(exchange_address=exchange_address),
+ params={"offset": 2, "limit": 2},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 6, "limit": 2, "offset": 2, "total": 6},
+ "deliveries": [
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 2,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": "2023-12-31T15:00:01+00:00",
+ "cancel_transaction_hash": "tx_hash_2",
+ "confirm_blocktimestamp": None,
+ "confirm_transaction_hash": None,
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": False,
+ "valid": False,
+ "status": DeliveryStatus.DELIVERY_CANCELED,
+ },
+ {
+ "exchange_address": exchange_address,
+ "delivery_id": 3,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": "2023-12-31T15:00:02+00:00",
+ "confirm_transaction_hash": "tx_hash_3",
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": True,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_CONFIRMED,
+ },
+ ],
+ }
+
+ # ###########################################################################
+ # # Error Case
+ # ###########################################################################
+
+ # Error_1
+ # RequestValidationError
+ # query(invalid value)
+ def test_error_1(self, client, db):
+ exchange_address = "0x1234567890123456789012345678900000000000"
+
+ # request target api
+ resp = client.get(
+ self.base_url.format(exchange_address=exchange_address),
+ params={
+ "valid": "invalid_value",
+ "status": "invalid_value",
+ "crate_blocktimestamp_from": "invalid_value",
+ "crate_blocktimestamp_to": "invalid_value",
+ "sort_item": "test",
+ "offset": "test",
+ "limit": "test",
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 422
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "type": "bool_parsing",
+ "loc": ["query", "valid"],
+ "msg": "Input should be a valid boolean, unable to interpret input",
+ "input": "invalid_value",
+ },
+ {
+ "type": "enum",
+ "loc": ["query", "status"],
+ "msg": "Input should be 0, 1, 2, 3 or 4",
+ "input": "invalid_value",
+ "ctx": {"expected": "0, 1, 2, 3 or 4"},
+ },
+ {
+ "type": "int_parsing",
+ "loc": ["query", "offset"],
+ "msg": "Input should be a valid integer, unable to parse string as an integer",
+ "input": "test",
+ },
+ {
+ "type": "int_parsing",
+ "loc": ["query", "limit"],
+ "msg": "Input should be a valid integer, unable to parse string as an integer",
+ "input": "test",
+ },
+ ],
+ }
diff --git a/tests/app/test_settlement_dvp_{exchange_address}_deliveries_POST.py b/tests/app/test_settlement_dvp_{exchange_address}_deliveries_POST.py
new file mode 100644
index 00000000..d925621c
--- /dev/null
+++ b/tests/app/test_settlement_dvp_{exchange_address}_deliveries_POST.py
@@ -0,0 +1,734 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+import asyncio
+import hashlib
+import json
+
+from eth_keyfile import decode_keyfile_json
+
+from app.model.blockchain import IbetStraightBondContract
+from app.model.blockchain.tx_params.ibet_straight_bond import (
+ UpdateParams as IbetStraightBondUpdateParams,
+)
+from app.model.db import Account, AuthToken, Token, TokenType, TokenVersion
+from app.utils.contract_utils import ContractUtils
+from app.utils.e2ee_utils import E2EEUtils
+from config import CHAIN_ID, TX_GAS_LIMIT
+from tests.account_config import config_eth_account
+
+
+async def deploy_bond_token_contract(
+ address,
+ private_key,
+ personal_info_contract_address,
+ tradable_exchange_contract_address=None,
+ transfer_approval_required=None,
+):
+ arguments = [
+ "token.name",
+ "token.symbol",
+ 100,
+ 20,
+ "JPY",
+ "token.redemption_date",
+ 30,
+ "JPY",
+ "token.return_date",
+ "token.return_amount",
+ "token.purpose",
+ ]
+ bond_contrat = IbetStraightBondContract()
+ token_address, _, _ = await bond_contrat.create(arguments, address, private_key)
+ await bond_contrat.update(
+ data=IbetStraightBondUpdateParams(
+ transferable=True,
+ personal_info_contract_address=personal_info_contract_address,
+ tradable_exchange_contract_address=tradable_exchange_contract_address,
+ transfer_approval_required=transfer_approval_required,
+ ),
+ tx_from=address,
+ private_key=private_key,
+ )
+
+ return ContractUtils.get_contract("IbetStraightBond", token_address)
+
+
+class TestCreateDVPDeliveriesPOST:
+ # target API endpoint
+ base_url = "/settlement/dvp/{exchange_address}/deliveries"
+
+ ###########################################################################
+ # Normal Case
+ ###########################################################################
+
+ #
+ # Authorization by eoa-password
+ def test_normal_1(
+ self, ibet_security_token_dvp_contract, personal_info_contract, client, db
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ _keyfile = user_1["keyfile_json"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ agent_address = user_3["address"]
+ agent_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # prepare data
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = _keyfile
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ token_contract_1 = asyncio.run(
+ deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ )
+ )
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.tx_hash = ""
+ token.issuer_address = issuer_address
+ token.token_address = token_contract_1.address
+ token.abi = ""
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ db.commit()
+
+ # Transfer
+ tx = token_contract_1.functions.transferFrom(
+ issuer_address, ibet_security_token_dvp_contract.address, 40
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # request target API
+ req_param = {
+ "token_address": token_contract_1.address,
+ "buyer_address": user_address_1,
+ "amount": 10,
+ "agent_address": agent_address,
+ "data": json.dumps({}),
+ }
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address
+ ),
+ json=req_param,
+ headers={
+ "issuer-address": issuer_address,
+ "eoa-password": E2EEUtils.encrypt("password"),
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() is None
+
+ #
+ # Authorization by auth-token
+ def test_normal_2(
+ self, ibet_security_token_dvp_contract, personal_info_contract, client, db
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ _keyfile = user_1["keyfile_json"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ agent_address = user_3["address"]
+ agent_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # prepare data
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = _keyfile
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ token_contract_1 = asyncio.run(
+ deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ )
+ )
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.tx_hash = ""
+ token.issuer_address = issuer_address
+ token.token_address = token_contract_1.address
+ token.abi = ""
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ auth_token = AuthToken()
+ auth_token.issuer_address = issuer_address
+ auth_token.auth_token = hashlib.sha256("test_auth_token".encode()).hexdigest()
+ auth_token.valid_duration = 0
+ db.add(auth_token)
+
+ db.commit()
+
+ # Transfer
+ tx = token_contract_1.functions.transferFrom(
+ issuer_address, ibet_security_token_dvp_contract.address, 40
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # request target API
+ req_param = {
+ "token_address": token_contract_1.address,
+ "buyer_address": user_address_1,
+ "amount": 10,
+ "agent_address": agent_address,
+ "data": json.dumps({}),
+ }
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address
+ ),
+ json=req_param,
+ headers={
+ "issuer-address": issuer_address,
+ "auth-token": "test_auth_token",
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() is None
+
+ ###########################################################################
+ # Error Case
+ ###########################################################################
+
+ #
+ # RequestValidationError: buyer_address, agent_address
+ def test_error_1(self, client, db, ibet_security_token_dvp_contract):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ _keyfile = user_1["keyfile_json"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # prepare data
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.tx_hash = ""
+ token.issuer_address = issuer_address
+ token.token_address = "0x0000000000000000000000000000000000000000"
+ token.abi = ""
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ db.commit()
+
+ # request target API
+ req_param = {"buyer_address": "0x0", "agent_address": "0x0", "amount": 10}
+
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address
+ ),
+ json=req_param,
+ headers={
+ "issuer-address": issuer_address,
+ "eoa-password": E2EEUtils.encrypt("password"),
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 422
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "input": {
+ "agent_address": "0x0",
+ "amount": 10,
+ "buyer_address": "0x0",
+ },
+ "loc": ["body", "token_address"],
+ "msg": "Field required",
+ "type": "missing",
+ },
+ {
+ "ctx": {"error": {}},
+ "input": "0x0",
+ "loc": ["body", "buyer_address"],
+ "msg": "Value error, invalid ethereum address",
+ "type": "value_error",
+ },
+ {
+ "ctx": {"error": {}},
+ "input": "0x0",
+ "loc": ["body", "agent_address"],
+ "msg": "Value error, invalid ethereum address",
+ "type": "value_error",
+ },
+ {
+ "input": {
+ "agent_address": "0x0",
+ "amount": 10,
+ "buyer_address": "0x0",
+ },
+ "loc": ["body", "data"],
+ "msg": "Field required",
+ "type": "missing",
+ },
+ ],
+ }
+
+ #
+ # RequestValidationError: amount(min)
+ def test_error_2(self, client, db, ibet_security_token_dvp_contract):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ _keyfile = user_1["keyfile_json"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # prepare data
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.tx_hash = ""
+ token.issuer_address = issuer_address
+ token.token_address = "0x0000000000000000000000000000000000000000"
+ token.abi = ""
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ db.commit()
+
+ # request target API
+ req_param = {
+ "token_address": "0x0000000000000000000000000000000000000000",
+ "buyer_address": "0x0000000000000000000000000000000000000000",
+ "amount": 0,
+ "agent_address": "0x0000000000000000000000000000000000000000",
+ "data": json.dumps({}),
+ }
+
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address
+ ),
+ json=req_param,
+ headers={
+ "issuer-address": issuer_address,
+ "eoa-password": E2EEUtils.encrypt("password"),
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 422
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "ctx": {"ge": 1},
+ "input": 0,
+ "loc": ["body", "amount"],
+ "msg": "Input should be greater than or equal to 1",
+ "type": "greater_than_equal",
+ }
+ ],
+ }
+
+ #
+ # RequestValidationError: amount(max)
+ def test_error_3(self, client, db, ibet_security_token_dvp_contract):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ _keyfile = user_1["keyfile_json"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # request target API
+ req_param = {
+ "token_address": "0x0000000000000000000000000000000000000000",
+ "buyer_address": "0x0000000000000000000000000000000000000000",
+ "amount": 1_000_000_000_001,
+ "agent_address": "0x0000000000000000000000000000000000000000",
+ "data": json.dumps({}),
+ }
+
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address
+ ),
+ json=req_param,
+ headers={
+ "issuer-address": issuer_address,
+ "eoa-password": E2EEUtils.encrypt("password"),
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 422
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "ctx": {"le": 1000000000000},
+ "input": 1000000000001,
+ "loc": ["body", "amount"],
+ "msg": "Input should be less than or equal to 1000000000000",
+ "type": "less_than_equal",
+ }
+ ],
+ }
+
+ #
+ # RequestValidationError: headers and body required
+ def test_error_4(self, client, db, ibet_security_token_dvp_contract):
+ # request target API
+ resp = client.post(
+ self.base_url.format(
+ exchange_address="0x0000000000000000000000000000000000000000"
+ )
+ )
+
+ # assertion
+ assert resp.status_code == 422
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "input": None,
+ "loc": ["header", "issuer-address"],
+ "msg": "Field required",
+ "type": "missing",
+ },
+ {
+ "input": None,
+ "loc": ["body"],
+ "msg": "Field required",
+ "type": "missing",
+ },
+ ],
+ }
+
+ #
+ # RequestValidationError: issuer-address
+ def test_error_5(self, client, db, ibet_security_token_dvp_contract):
+ test_account = config_eth_account("user1")
+ issuer_address = test_account["address"]
+
+ # request target API
+ req_param = {
+ "token_address": "0x0000000000000000000000000000000000000000",
+ "buyer_address": "0x0000000000000000000000000000000000000000",
+ "amount": 1,
+ "agent_address": "0x0000000000000000000000000000000000000000",
+ "data": json.dumps({}),
+ }
+
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address
+ ),
+ json=req_param,
+ headers={"issuer-address": "issuer-address"},
+ )
+
+ # assertion
+ assert resp.status_code == 422
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "input": "issuer-address",
+ "loc": ["header", "issuer-address"],
+ "msg": "issuer-address is not a valid address",
+ "type": "value_error",
+ }
+ ],
+ }
+
+ #
+ # RequestValidationError: eoa-password(not decrypt)
+ def test_error_6(self, client, db, ibet_security_token_dvp_contract):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ _keyfile = user_1["keyfile_json"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # prepare data
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = _keyfile
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ db.commit()
+
+ # request target API
+ req_param = {
+ "token_address": "0x0000000000000000000000000000000000000000",
+ "buyer_address": "0x0000000000000000000000000000000000000000",
+ "amount": 1,
+ "agent_address": "0x0000000000000000000000000000000000000000",
+ "data": json.dumps({}),
+ }
+
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address
+ ),
+ json=req_param,
+ headers={"issuer-address": issuer_address, "eoa-password": "password"},
+ )
+
+ assert resp.status_code == 422
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "input": "password",
+ "loc": ["header", "eoa-password"],
+ "msg": "eoa-password is not a Base64-encoded encrypted data",
+ "type": "value_error",
+ }
+ ],
+ }
+
+ #
+ # issuer does not exist
+ def test_error_7(self, client, db, ibet_security_token_dvp_contract):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ _keyfile = user_1["keyfile_json"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # prepare data
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.tx_hash = ""
+ token.issuer_address = issuer_address
+ token.token_address = "0x0000000000000000000000000000000000000000"
+ token.abi = ""
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ db.commit()
+
+ # request target API
+ req_param = {
+ "token_address": "0x0000000000000000000000000000000000000000",
+ "buyer_address": "0x0000000000000000000000000000000000000000",
+ "amount": 1,
+ "agent_address": "0x0000000000000000000000000000000000000000",
+ "data": json.dumps({}),
+ }
+
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address
+ ),
+ json=req_param,
+ headers={
+ "issuer-address": issuer_address,
+ "eoa-password": E2EEUtils.encrypt("password"),
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 401
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "AuthorizationError"},
+ "detail": "issuer does not exist, or password mismatch",
+ }
+
+ #
+ # password mismatch
+ def test_error_8(self, client, db, ibet_security_token_dvp_contract):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ _keyfile = user_1["keyfile_json"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # prepare data
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = _keyfile
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ db.commit()
+
+ # request target API
+ req_param = {
+ "token_address": "0x0000000000000000000000000000000000000000",
+ "buyer_address": "0x0000000000000000000000000000000000000000",
+ "amount": 1,
+ "agent_address": "0x0000000000000000000000000000000000000000",
+ "data": json.dumps({}),
+ }
+
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address
+ ),
+ json=req_param,
+ headers={
+ "issuer-address": issuer_address,
+ "eoa-password": E2EEUtils.encrypt("password_test"),
+ },
+ )
+
+ assert resp.status_code == 401
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "AuthorizationError"},
+ "detail": "issuer does not exist, or password mismatch",
+ }
+
+ #
+ # Send Transaction Error
+ def test_error_9(
+ self, client, db, ibet_security_token_dvp_contract, personal_info_contract
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ _keyfile = user_1["keyfile_json"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ agent_address = user_3["address"]
+ agent_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # prepare data
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = _keyfile
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ token_contract_1 = asyncio.run(
+ deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ )
+ )
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.tx_hash = ""
+ token.issuer_address = issuer_address
+ token.token_address = token_contract_1.address
+ token.abi = ""
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ db.commit()
+
+ # Transfer
+ tx = token_contract_1.functions.transferFrom(
+ issuer_address, ibet_security_token_dvp_contract.address, 40
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # request target API
+ req_param = {
+ "token_address": token_contract_1.address,
+ "buyer_address": user_address_1,
+ "amount": 50,
+ "agent_address": agent_address,
+ "data": json.dumps({}),
+ }
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address
+ ),
+ json=req_param,
+ headers={
+ "issuer-address": issuer_address,
+ "eoa-password": E2EEUtils.encrypt("password"),
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 400
+ assert resp.json() == {
+ "meta": {"code": 2, "title": "SendTransactionError"},
+ "detail": "failed to create delivery",
+ }
diff --git a/tests/app/test_settlement_dvp_{exchange_address}_delivery_{delivery_id}_GET.py b/tests/app/test_settlement_dvp_{exchange_address}_delivery_{delivery_id}_GET.py
new file mode 100644
index 00000000..d3583edc
--- /dev/null
+++ b/tests/app/test_settlement_dvp_{exchange_address}_delivery_{delivery_id}_GET.py
@@ -0,0 +1,119 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+from datetime import UTC, datetime
+
+from app.model.db import DeliveryStatus, IDXDelivery
+from tests.account_config import config_eth_account
+
+
+class TestAppRoutersShareTokensTokenAddressRedeemBatchBatchIdGET:
+ # target API endpoint
+ base_url = "/settlement/dvp/{exchange_address}/delivery/{delivery_id}"
+
+ account_list = [
+ {"address": config_eth_account("user1")["address"], "amount": 1},
+ {"address": config_eth_account("user2")["address"], "amount": 2},
+ ]
+
+ ###########################################################################
+ # Normal Case
+ ###########################################################################
+
+ # Normal_1
+ def test_normal_1_1(self, client, db):
+ exchange_address = "0x1234567890123456789012345678900000000000"
+ token_address_1 = "0x1234567890123456789012345678900000000010"
+
+ seller_address_1 = "0x1234567890123456789012345678900000000100"
+
+ buyer_address = "0x1234567890123456789012345678911111111111"
+
+ agent_address_1 = "0x1234567890123456789012345678900000001000"
+
+ # prepare data: IDXDelivery(Created)
+ _idx_delivery = IDXDelivery()
+ _idx_delivery.exchange_address = exchange_address
+ _idx_delivery.delivery_id = 1
+ _idx_delivery.token_address = token_address_1
+ _idx_delivery.buyer_address = buyer_address
+ _idx_delivery.seller_address = seller_address_1
+ _idx_delivery.amount = 1
+ _idx_delivery.agent_address = agent_address_1
+ _idx_delivery.data = ""
+ _idx_delivery.create_blocktimestamp = datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
+ _idx_delivery.create_transaction_hash = "tx_hash_1"
+ _idx_delivery.confirmed = False
+ _idx_delivery.valid = True
+ _idx_delivery.status = DeliveryStatus.DELIVERY_CREATED.value
+ db.add(_idx_delivery)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(exchange_address=exchange_address, delivery_id=1),
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "exchange_address": exchange_address,
+ "delivery_id": 1,
+ "token_address": token_address_1,
+ "buyer_address": buyer_address,
+ "seller_address": seller_address_1,
+ "amount": 1,
+ "agent_address": agent_address_1,
+ "data": "",
+ "create_blocktimestamp": "2023-12-31T15:00:00+00:00",
+ "create_transaction_hash": "tx_hash_1",
+ "cancel_blocktimestamp": None,
+ "cancel_transaction_hash": None,
+ "confirm_blocktimestamp": None,
+ "confirm_transaction_hash": None,
+ "finish_blocktimestamp": None,
+ "finish_transaction_hash": None,
+ "abort_blocktimestamp": None,
+ "abort_transaction_hash": None,
+ "confirmed": False,
+ "valid": True,
+ "status": DeliveryStatus.DELIVERY_CREATED,
+ }
+
+ #########################################################################
+ # Error Case
+ ###########################################################################
+
+ # Error_1
+ # NotFound
+ def test_error_1(self, client, db):
+ exchange_address = "0x1234567890123456789012345678900000000000"
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(exchange_address=exchange_address, delivery_id=1),
+ )
+
+ # assertion
+ assert resp.status_code == 404
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "NotFound"},
+ "detail": "delivery not found",
+ }
diff --git a/tests/app/test_settlement_dvp_{exchange_address}_delivery_{delivery_id}_POST.py b/tests/app/test_settlement_dvp_{exchange_address}_delivery_{delivery_id}_POST.py
new file mode 100644
index 00000000..d77574bb
--- /dev/null
+++ b/tests/app/test_settlement_dvp_{exchange_address}_delivery_{delivery_id}_POST.py
@@ -0,0 +1,950 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+import asyncio
+import hashlib
+
+import pytest
+from eth_keyfile import decode_keyfile_json
+
+from app.model.blockchain import IbetStraightBondContract
+from app.model.blockchain.tx_params.ibet_straight_bond import (
+ UpdateParams as IbetStraightBondUpdateParams,
+)
+from app.model.db import (
+ Account,
+ AuthToken,
+ DVPAgentAccount,
+ Token,
+ TokenType,
+ TokenVersion,
+)
+from app.utils.contract_utils import ContractUtils
+from app.utils.e2ee_utils import E2EEUtils
+from config import CHAIN_ID, TX_GAS_LIMIT
+from tests.account_config import config_eth_account
+
+
+async def deploy_bond_token_contract(
+ address,
+ private_key,
+ personal_info_contract_address,
+ tradable_exchange_contract_address=None,
+ transfer_approval_required=None,
+):
+ arguments = [
+ "token.name",
+ "token.symbol",
+ 100,
+ 20,
+ "JPY",
+ "token.redemption_date",
+ 30,
+ "JPY",
+ "token.return_date",
+ "token.return_amount",
+ "token.purpose",
+ ]
+ bond_contrat = IbetStraightBondContract()
+ token_address, _, _ = await bond_contrat.create(arguments, address, private_key)
+ await bond_contrat.update(
+ data=IbetStraightBondUpdateParams(
+ transferable=True,
+ personal_info_contract_address=personal_info_contract_address,
+ tradable_exchange_contract_address=tradable_exchange_contract_address,
+ transfer_approval_required=transfer_approval_required,
+ ),
+ tx_from=address,
+ private_key=private_key,
+ )
+
+ return ContractUtils.get_contract("IbetStraightBond", token_address)
+
+
+class TestUpdateDVPDeliveryPOST:
+ # target API endpoint
+ base_url = "/settlement/dvp/{exchange_address}/delivery/{delivery_id}"
+
+ ###########################################################################
+ # Normal Case
+ ###########################################################################
+
+ #
+ # Cancel Delivery
+ # Authorization by eoa-password
+ def test_normal_1_1(
+ self, ibet_security_token_dvp_contract, personal_info_contract, client, db
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ _keyfile = user_1["keyfile_json"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ agent_address = user_3["address"]
+ agent_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # prepare data
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = _keyfile
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ dvp_agent_account = DVPAgentAccount()
+ dvp_agent_account.account_address = agent_address
+ dvp_agent_account.keyfile = user_3["keyfile_json"]
+ dvp_agent_account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(dvp_agent_account)
+
+ token_contract_1 = asyncio.run(
+ deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ )
+ )
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.tx_hash = ""
+ token.issuer_address = issuer_address
+ token.token_address = token_contract_1.address
+ token.abi = ""
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ db.commit()
+
+ # Transfer
+ tx = token_contract_1.functions.transferFrom(
+ issuer_address, ibet_security_token_dvp_contract.address, 40
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # CreateDelivery
+ tx = ibet_security_token_dvp_contract.functions.createDelivery(
+ token_contract_1.address, user_address_1, 30, agent_address, "." * 1000
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # request target API
+ req_param = {"operation_type": "Cancel"}
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address,
+ delivery_id=1,
+ ),
+ json=req_param,
+ headers={
+ "issuer-address": issuer_address,
+ "eoa-password": E2EEUtils.encrypt("password"),
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() is None
+
+ #
+ # Cancel Delivery
+ # Authorization by auth-token
+ def test_normal_1_2(
+ self, ibet_security_token_dvp_contract, personal_info_contract, client, db
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ _keyfile = user_1["keyfile_json"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ agent_address = user_3["address"]
+ agent_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # prepare data
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = _keyfile
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ dvp_agent_account = DVPAgentAccount()
+ dvp_agent_account.account_address = agent_address
+ dvp_agent_account.keyfile = user_3["keyfile_json"]
+ dvp_agent_account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(dvp_agent_account)
+
+ token_contract_1 = asyncio.run(
+ deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ )
+ )
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.tx_hash = ""
+ token.issuer_address = issuer_address
+ token.token_address = token_contract_1.address
+ token.abi = ""
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ auth_token = AuthToken()
+ auth_token.issuer_address = issuer_address
+ auth_token.auth_token = hashlib.sha256("test_auth_token".encode()).hexdigest()
+ auth_token.valid_duration = 0
+ db.add(auth_token)
+
+ db.commit()
+
+ # Transfer
+ tx = token_contract_1.functions.transferFrom(
+ issuer_address, ibet_security_token_dvp_contract.address, 40
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # CreateDelivery
+ tx = ibet_security_token_dvp_contract.functions.createDelivery(
+ token_contract_1.address, user_address_1, 30, agent_address, "." * 1000
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # request target API
+ req_param = {"operation_type": "Cancel"}
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address,
+ delivery_id=1,
+ ),
+ json=req_param,
+ headers={
+ "issuer-address": issuer_address,
+ "auth-token": "test_auth_token",
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() is None
+
+ #
+ # Finish Delivery
+ def test_normal_2(
+ self, ibet_security_token_dvp_contract, personal_info_contract, client, db
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ _keyfile = user_1["keyfile_json"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ agent_address = user_3["address"]
+ agent_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # prepare data
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = _keyfile
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ dvp_agent_account = DVPAgentAccount()
+ dvp_agent_account.account_address = agent_address
+ dvp_agent_account.keyfile = user_3["keyfile_json"]
+ dvp_agent_account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(dvp_agent_account)
+
+ token_contract_1 = asyncio.run(
+ deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ )
+ )
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.tx_hash = ""
+ token.issuer_address = issuer_address
+ token.token_address = token_contract_1.address
+ token.abi = ""
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ db.commit()
+
+ # Transfer
+ tx = token_contract_1.functions.transferFrom(
+ issuer_address, ibet_security_token_dvp_contract.address, 40
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # CreateDelivery
+ tx = ibet_security_token_dvp_contract.functions.createDelivery(
+ token_contract_1.address, user_address_1, 30, agent_address, "." * 1000
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # ConfirmDelivery
+ tx = ibet_security_token_dvp_contract.functions.confirmDelivery(
+ 1
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": user_address_1,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, user_private_key_1)
+
+ # request target API
+ req_param = {
+ "operation_type": "Finish",
+ "account_address": agent_address,
+ "eoa_password": E2EEUtils.encrypt("password"),
+ }
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address,
+ delivery_id=1,
+ ),
+ json=req_param,
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() is None
+
+ #
+ # Finish Delivery
+ def test_normal_3(
+ self, ibet_security_token_dvp_contract, personal_info_contract, client, db
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ _keyfile = user_1["keyfile_json"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ agent_address = user_3["address"]
+ agent_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # prepare data
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = _keyfile
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ dvp_agent_account = DVPAgentAccount()
+ dvp_agent_account.account_address = agent_address
+ dvp_agent_account.keyfile = user_3["keyfile_json"]
+ dvp_agent_account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(dvp_agent_account)
+
+ token_contract_1 = asyncio.run(
+ deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ )
+ )
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.tx_hash = ""
+ token.issuer_address = issuer_address
+ token.token_address = token_contract_1.address
+ token.abi = ""
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ db.commit()
+
+ # Transfer
+ tx = token_contract_1.functions.transferFrom(
+ issuer_address, ibet_security_token_dvp_contract.address, 40
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # CreateDelivery
+ tx = ibet_security_token_dvp_contract.functions.createDelivery(
+ token_contract_1.address, user_address_1, 30, agent_address, "." * 1000
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # ConfirmDelivery
+ tx = ibet_security_token_dvp_contract.functions.confirmDelivery(
+ 1
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": user_address_1,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, user_private_key_1)
+
+ # request target API
+ req_param = {
+ "operation_type": "Finish",
+ "account_address": agent_address,
+ "eoa_password": E2EEUtils.encrypt("password"),
+ }
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address,
+ delivery_id=1,
+ ),
+ json=req_param,
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() is None
+
+ ###########################################################################
+ # Error Case
+ ###########################################################################
+
+ #
+ # RequestValidationError: operation_type
+ def test_error_1(self, client, db, ibet_security_token_dvp_contract):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ _keyfile = user_1["keyfile_json"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # request target API
+ req_param = {"operation_type": "invalid_value"}
+
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address, delivery_id=1
+ ),
+ json=req_param,
+ headers={
+ "issuer-address": issuer_address,
+ "eoa-password": E2EEUtils.encrypt("password"),
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 422
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "ctx": {"expected": "'Cancel'"},
+ "input": "invalid_value",
+ "loc": ["body", "CancelDVPDeliveryRequest", "operation_type"],
+ "msg": "Input should be 'Cancel'",
+ "type": "literal_error",
+ },
+ {
+ "ctx": {"expected": "'Finish'"},
+ "input": "invalid_value",
+ "loc": ["body", "FinishDVPDeliveryRequest", "operation_type"],
+ "msg": "Input should be 'Finish'",
+ "type": "literal_error",
+ },
+ {
+ "input": {"operation_type": "invalid_value"},
+ "loc": ["body", "FinishDVPDeliveryRequest", "account_address"],
+ "msg": "Field required",
+ "type": "missing",
+ },
+ {
+ "input": {"operation_type": "invalid_value"},
+ "loc": ["body", "FinishDVPDeliveryRequest", "eoa_password"],
+ "msg": "Field required",
+ "type": "missing",
+ },
+ {
+ "ctx": {"expected": "'Abort'"},
+ "input": "invalid_value",
+ "loc": ["body", "AbortDVPDeliveryRequest", "operation_type"],
+ "msg": "Input should be 'Abort'",
+ "type": "literal_error",
+ },
+ {
+ "input": {"operation_type": "invalid_value"},
+ "loc": ["body", "AbortDVPDeliveryRequest", "account_address"],
+ "msg": "Field required",
+ "type": "missing",
+ },
+ {
+ "input": {"operation_type": "invalid_value"},
+ "loc": ["body", "AbortDVPDeliveryRequest", "eoa_password"],
+ "msg": "Field required",
+ "type": "missing",
+ },
+ ],
+ }
+
+ #
+ # RequestValidationError: headers and body required
+ def test_error_2(self, client, db, ibet_security_token_dvp_contract):
+ # request target API
+ resp = client.post(
+ self.base_url.format(
+ exchange_address="0x0000000000000000000000000000000000000000",
+ delivery_id=1,
+ )
+ )
+
+ # assertion
+ assert resp.status_code == 422
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "input": None,
+ "loc": ["body"],
+ "msg": "Field required",
+ "type": "missing",
+ }
+ ],
+ }
+
+ #
+ # RequestValidationError: issuer-address
+ def test_error_3(self, client, db, ibet_security_token_dvp_contract):
+ test_account = config_eth_account("user1")
+ issuer_address = test_account["address"]
+
+ # request target API
+ req_param = {
+ "operation_type": "Cancel",
+ }
+
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address, delivery_id=1
+ ),
+ json=req_param,
+ headers={"issuer-address": "issuer-address"},
+ )
+
+ # assertion
+ assert resp.status_code == 422
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "input": "issuer-address",
+ "loc": ["header", "issuer-address"],
+ "msg": "issuer-address is not a valid address",
+ "type": "value_error",
+ }
+ ],
+ }
+
+ #
+ # RequestValidationError: eoa-password(not decrypt)
+ def test_error_4(self, client, db, ibet_security_token_dvp_contract):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ _keyfile = user_1["keyfile_json"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # prepare data
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = _keyfile
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ db.commit()
+
+ # request target API
+ req_param = {
+ "operation_type": "Cancel",
+ }
+
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address, delivery_id=1
+ ),
+ json=req_param,
+ headers={"issuer-address": issuer_address, "eoa-password": "password"},
+ )
+
+ assert resp.status_code == 422
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "input": "password",
+ "loc": ["header", "eoa-password"],
+ "msg": "eoa-password is not a Base64-encoded encrypted data",
+ "type": "value_error",
+ }
+ ],
+ }
+
+ #
+ # issuer does not exist
+ def test_error_5(self, client, db, ibet_security_token_dvp_contract):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ _keyfile = user_1["keyfile_json"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # prepare data
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.tx_hash = ""
+ token.issuer_address = issuer_address
+ token.token_address = "0x0000000000000000000000000000000000000000"
+ token.abi = ""
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ db.commit()
+
+ # request target API
+ req_param = {
+ "operation_type": "Cancel",
+ }
+
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address, delivery_id=1
+ ),
+ json=req_param,
+ headers={
+ "issuer-address": issuer_address,
+ "eoa-password": E2EEUtils.encrypt("password"),
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 401
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "AuthorizationError"},
+ "detail": "issuer does not exist, or password mismatch",
+ }
+
+ #
+ # password mismatch
+ def test_error_6(self, client, db, ibet_security_token_dvp_contract):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ _keyfile = user_1["keyfile_json"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # prepare data
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = _keyfile
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ db.commit()
+
+ # request target API
+ req_param = {
+ "operation_type": "Cancel",
+ }
+
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address, delivery_id=1
+ ),
+ json=req_param,
+ headers={
+ "issuer-address": issuer_address,
+ "eoa-password": E2EEUtils.encrypt("password_test"),
+ },
+ )
+
+ assert resp.status_code == 401
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "AuthorizationError"},
+ "detail": "issuer does not exist, or password mismatch",
+ }
+
+ #
+ # DVP agent account not found
+ @pytest.mark.parametrize(
+ "operation_type",
+ ["Finish", "Abort"],
+ )
+ def test_error_7(
+ self, operation_type, client, db, ibet_security_token_dvp_contract
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ _keyfile = user_1["keyfile_json"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # prepare data
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = _keyfile
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ db.commit()
+
+ # request target API
+ req_param = {
+ "operation_type": operation_type,
+ "account_address": "0x0000000000000000000000000000000000000000",
+ "eoa_password": "password",
+ }
+
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address, delivery_id=1
+ ),
+ json=req_param,
+ )
+
+ assert resp.status_code == 404, resp.json()
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "NotFound"},
+ "detail": "agent account is not exists",
+ }
+
+ #
+ # Send Transaction Error
+ @pytest.mark.parametrize(
+ "operation_type",
+ ["Finish", "Abort"],
+ )
+ def test_error_8(
+ self,
+ operation_type,
+ client,
+ db,
+ ibet_security_token_dvp_contract,
+ personal_info_contract,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ _keyfile = user_1["keyfile_json"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ agent_address = user_3["address"]
+ agent_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # prepare data
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = _keyfile
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ dvp_agent_account = DVPAgentAccount()
+ dvp_agent_account.account_address = agent_address
+ dvp_agent_account.keyfile = user_3["keyfile_json"]
+ dvp_agent_account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(dvp_agent_account)
+
+ token_contract_1 = asyncio.run(
+ deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ )
+ )
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.tx_hash = ""
+ token.issuer_address = issuer_address
+ token.token_address = token_contract_1.address
+ token.abi = ""
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ db.commit()
+
+ # Transfer
+ tx = token_contract_1.functions.transferFrom(
+ issuer_address, ibet_security_token_dvp_contract.address, 40
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # CreateDelivery
+ tx = ibet_security_token_dvp_contract.functions.createDelivery(
+ token_contract_1.address, user_address_1, 30, agent_address, "." * 1000
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # ConfirmDelivery
+ tx = ibet_security_token_dvp_contract.functions.confirmDelivery(
+ 1
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": user_address_1,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, user_private_key_1)
+
+ # request target API
+ req_param = {
+ "operation_type": operation_type,
+ "account_address": agent_address,
+ "eoa_password": E2EEUtils.encrypt("password"),
+ }
+ resp = client.post(
+ self.base_url.format(
+ exchange_address=ibet_security_token_dvp_contract.address,
+ delivery_id=2,
+ ),
+ json=req_param,
+ )
+
+ # assertion
+ assert resp.status_code == 400
+ assert resp.json() == {
+ "meta": {"code": 2, "title": "SendTransactionError"},
+ "detail": f"failed to {operation_type.lower()} delivery",
+ }
diff --git a/tests/test_app_routers_share_bulk_transfer_GET.py b/tests/app/test_share_bulk_transfer_GET.py
similarity index 97%
rename from tests/test_app_routers_share_bulk_transfer_GET.py
rename to tests/app/test_share_bulk_transfer_GET.py
index 57c342a8..37ed19fe 100644
--- a/tests/test_app_routers_share_bulk_transfer_GET.py
+++ b/tests/app/test_share_bulk_transfer_GET.py
@@ -17,7 +17,7 @@
SPDX-License-Identifier: Apache-2.0
"""
-from datetime import datetime
+from datetime import UTC, datetime
import pytest
import pytz
@@ -70,7 +70,7 @@ def test_normal_1(self, client, db):
db.add(account)
# prepare data : BulkTransferUpload
- utc_now = datetime.utcnow()
+ utc_now = datetime.now(UTC).replace(tzinfo=None)
for i in range(0, 3):
bulk_transfer_upload = BulkTransferUpload()
bulk_transfer_upload.issuer_address = self.upload_issuer_list[i]["address"]
@@ -110,7 +110,7 @@ def test_normal_1(self, client, db):
@pytest.mark.freeze_time("2021-05-20 12:34:56")
def test_normal_2(self, client, db):
# prepare data : BulkTransferUpload
- utc_now = datetime.utcnow()
+ utc_now = datetime.now(UTC).replace(tzinfo=None)
for i in range(0, 3):
bulk_transfer_upload = BulkTransferUpload()
bulk_transfer_upload.issuer_address = self.upload_issuer_list[i]["address"]
diff --git a/tests/test_app_routers_share_bulk_transfer_POST.py b/tests/app/test_share_bulk_transfer_POST.py
similarity index 98%
rename from tests/test_app_routers_share_bulk_transfer_POST.py
rename to tests/app/test_share_bulk_transfer_POST.py
index 4de51217..2710b566 100644
--- a/tests/test_app_routers_share_bulk_transfer_POST.py
+++ b/tests/app/test_share_bulk_transfer_POST.py
@@ -84,7 +84,7 @@ def test_normal_1(self, client, db):
_token.issuer_address = self.admin_address
_token.token_address = _t
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -174,7 +174,7 @@ def test_normal_2(self, client, db):
_token.issuer_address = self.admin_address
_token.token_address = _t
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -257,7 +257,7 @@ def test_normal_3(self, client, db):
_token.issuer_address = self.from_address
_token.token_address = _t
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -697,7 +697,7 @@ def test_error_10(self, client, db):
_token.token_address = self.req_tokens[0]
_token.abi = ""
_token.token_status = 0
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -747,7 +747,7 @@ def test_error_11_1(self, client, db):
_token.issuer_address = self.from_address
_token.token_address = _t
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -805,7 +805,7 @@ def test_error_11_2(self, client, db):
_token.issuer_address = self.from_address
_token.token_address = _t
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -863,7 +863,7 @@ def test_error_11_3(self, client, db):
_token.issuer_address = self.admin_address
_token.token_address = _t
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
diff --git a/tests/test_app_routers_share_bulk_transfer_{upload_id}_GET.py b/tests/app/test_share_bulk_transfer_{upload_id}_GET.py
similarity index 100%
rename from tests/test_app_routers_share_bulk_transfer_{upload_id}_GET.py
rename to tests/app/test_share_bulk_transfer_{upload_id}_GET.py
diff --git a/tests/test_app_routers_share_lock_events_GET.py b/tests/app/test_share_lock_events_GET.py
similarity index 97%
rename from tests/test_app_routers_share_lock_events_GET.py
rename to tests/app/test_share_lock_events_GET.py
index 16ca2ca2..8c8c391e 100644
--- a/tests/test_app_routers_share_lock_events_GET.py
+++ b/tests/app/test_share_lock_events_GET.py
@@ -17,7 +17,7 @@
SPDX-License-Identifier: Apache-2.0
"""
-from datetime import datetime
+from datetime import UTC, datetime
from unittest import mock
from unittest.mock import ANY, AsyncMock
@@ -56,7 +56,7 @@ def setup_data(self, db: Session, token_status: int = 1):
_token.tx_hash = ""
_token.abi = ""
_token.token_status = token_status
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Token
@@ -67,7 +67,7 @@ def setup_data(self, db: Session, token_status: int = 1):
_token.tx_hash = ""
_token.abi = ""
_token.token_status = token_status
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Lock events
@@ -80,7 +80,7 @@ def setup_data(self, db: Session, token_status: int = 1):
_lock.account_address = self.account_address_1
_lock.value = 1
_lock.data = {"message": "locked_1"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
_lock = IDXLock()
@@ -92,7 +92,7 @@ def setup_data(self, db: Session, token_status: int = 1):
_lock.account_address = self.account_address_2
_lock.value = 1
_lock.data = {"message": "locked_2"}
- _lock.block_timestamp = datetime.utcnow()
+ _lock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_lock)
_unlock = IDXUnlock()
@@ -105,7 +105,7 @@ def setup_data(self, db: Session, token_status: int = 1):
_unlock.recipient_address = self.other_account_address_1
_unlock.value = 1
_unlock.data = {"message": "unlocked_1"}
- _unlock.block_timestamp = datetime.utcnow()
+ _unlock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_unlock)
_unlock = IDXUnlock()
@@ -118,7 +118,7 @@ def setup_data(self, db: Session, token_status: int = 1):
_unlock.recipient_address = self.other_account_address_2
_unlock.value = 1
_unlock.data = {"message": "unlocked_2"}
- _unlock.block_timestamp = datetime.utcnow()
+ _unlock.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_unlock)
db.commit()
@@ -207,7 +207,7 @@ def test_normal_1(self, client, db):
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
diff --git a/tests/test_app_routers_share_tokens_GET.py b/tests/app/test_share_tokens_GET.py
similarity index 93%
rename from tests/test_app_routers_share_tokens_GET.py
rename to tests/app/test_share_tokens_GET.py
index f9c98616..afe6ba70 100644
--- a/tests/test_app_routers_share_tokens_GET.py
+++ b/tests/app/test_share_tokens_GET.py
@@ -57,7 +57,7 @@ def test_normal_2(self, mock_get, client, db):
token.issuer_address = issuer_address_1
token.token_address = "token_address_test1"
token.abi = "abi_test1"
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -91,6 +91,7 @@ def test_normal_2(self, mock_get, client, db):
mock_token.personal_info_contract_address = (
"0x1234567890aBcDFE1234567890abcDFE12345679"
)
+ mock_token.require_personal_info_registered = True
mock_token.principal_value = 1000
mock_token.transfer_approval_required = False
mock_token.is_canceled = False
@@ -120,11 +121,12 @@ def test_normal_2(self, mock_get, client, db):
"transfer_approval_required": False,
"is_offering": True,
"personal_info_contract_address": "0x1234567890aBcDFE1234567890abcDFE12345679",
+ "require_personal_info_registered": True,
"is_canceled": False,
"issue_datetime": _issue_datetime,
"token_status": 1,
"memo": "memo_test1",
- "contract_version": TokenVersion.V_22_12,
+ "contract_version": TokenVersion.V_24_06,
}
]
@@ -146,7 +148,7 @@ def test_normal_3(self, mock_get, client, db):
token_1.issuer_address = issuer_address_1
token_1.token_address = "token_address_test1"
token_1.abi = "abi_test1"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -179,6 +181,7 @@ def test_normal_3(self, mock_get, client, db):
mock_token_1.personal_info_contract_address = (
"0x1234567890aBcDFE1234567890abcDFE12345679"
)
+ mock_token_1.require_personal_info_registered = True
mock_token_1.principal_value = 1000
mock_token_1.transfer_approval_required = False
mock_token_1.is_canceled = False
@@ -192,7 +195,7 @@ def test_normal_3(self, mock_get, client, db):
token_2.token_address = "token_address_test2"
token_2.abi = "abi_test2"
token_2.token_status = 0
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -225,6 +228,7 @@ def test_normal_3(self, mock_get, client, db):
mock_token_2.personal_info_contract_address = (
"0x1234567890aBcDFE1234567890abcDFE12345679"
)
+ mock_token_2.require_personal_info_registered = False
mock_token_2.principal_value = 1000
mock_token_2.transfer_approval_required = False
mock_token_2.is_canceled = False
@@ -255,11 +259,12 @@ def test_normal_3(self, mock_get, client, db):
"transfer_approval_required": False,
"is_offering": True,
"personal_info_contract_address": "0x1234567890aBcDFE1234567890abcDFE12345679",
+ "require_personal_info_registered": True,
"is_canceled": False,
"issue_datetime": _issue_datetime_1,
"token_status": 1,
"memo": "memo_test1",
- "contract_version": TokenVersion.V_22_12,
+ "contract_version": TokenVersion.V_24_06,
},
{
"issuer_address": issuer_address_2,
@@ -281,11 +286,12 @@ def test_normal_3(self, mock_get, client, db):
"transfer_approval_required": False,
"is_offering": True,
"personal_info_contract_address": "0x1234567890aBcDFE1234567890abcDFE12345679",
+ "require_personal_info_registered": False,
"is_canceled": False,
"issue_datetime": _issue_datetime_2,
"token_status": 0,
"memo": "memo_test2",
- "contract_version": TokenVersion.V_22_12,
+ "contract_version": TokenVersion.V_24_06,
},
]
@@ -304,7 +310,7 @@ def test_normal_4(self, client, db):
token.issuer_address = "issuer_address_test1"
token.token_address = "token_address_test1"
token.abi = "abi_test1"
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
resp = client.get(self.apiurl, headers={"issuer-address": issuer_address_1})
@@ -327,7 +333,7 @@ def test_normal_5(self, mock_get, client, db):
token_1.issuer_address = issuer_address_1
token_1.token_address = "token_address_test1"
token_1.abi = "abi_test1"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
_issue_datetime = (
@@ -359,6 +365,7 @@ def test_normal_5(self, mock_get, client, db):
mock_token.personal_info_contract_address = (
"0x1234567890aBcDFE1234567890abcDFE12345679"
)
+ mock_token.require_personal_info_registered = True
mock_token.principal_value = 1000
mock_token.transfer_approval_required = False
mock_token.is_canceled = False
@@ -372,7 +379,7 @@ def test_normal_5(self, mock_get, client, db):
token_2.issuer_address = issuer_address_2
token_2.token_address = "token_address_test1"
token_2.abi = "abi_test1"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
resp = client.get(self.apiurl, headers={"issuer-address": issuer_address_1})
@@ -398,11 +405,12 @@ def test_normal_5(self, mock_get, client, db):
"transfer_approval_required": False,
"is_offering": True,
"personal_info_contract_address": "0x1234567890aBcDFE1234567890abcDFE12345679",
+ "require_personal_info_registered": True,
"is_canceled": False,
"issue_datetime": _issue_datetime,
"token_status": 1,
"memo": "memo_test1",
- "contract_version": TokenVersion.V_22_12,
+ "contract_version": TokenVersion.V_24_06,
}
]
@@ -424,7 +432,7 @@ def test_normal_6(self, mock_get, client, db):
token_1.issuer_address = issuer_address_1
token_1.token_address = "token_address_test1"
token_1.abi = "abi_test1"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -457,6 +465,7 @@ def test_normal_6(self, mock_get, client, db):
mock_token_1.personal_info_contract_address = (
"0x1234567890aBcDFE1234567890abcDFE12345679"
)
+ mock_token_1.require_personal_info_registered = True
mock_token_1.principal_value = 1000
mock_token_1.transfer_approval_required = False
mock_token_1.is_canceled = False
@@ -470,7 +479,7 @@ def test_normal_6(self, mock_get, client, db):
token_2.token_address = "token_address_test2"
token_2.abi = "abi_test2"
token_2.token_status = 0
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -503,6 +512,7 @@ def test_normal_6(self, mock_get, client, db):
mock_token_2.personal_info_contract_address = (
"0x1234567890aBcDFE1234567890abcDFE12345679"
)
+ mock_token_2.require_personal_info_registered = True
mock_token_2.principal_value = 1000
mock_token_2.transfer_approval_required = False
mock_token_2.is_canceled = False
@@ -517,7 +527,7 @@ def test_normal_6(self, mock_get, client, db):
token_3.issuer_address = issuer_address_2
token_3.token_address = "token_address_test1"
token_3.abi = "abi_test1"
- token_3.version = TokenVersion.V_22_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
resp = client.get(self.apiurl, headers={"issuer-address": issuer_address_1})
@@ -543,11 +553,12 @@ def test_normal_6(self, mock_get, client, db):
"transfer_approval_required": False,
"is_offering": True,
"personal_info_contract_address": "0x1234567890aBcDFE1234567890abcDFE12345679",
+ "require_personal_info_registered": True,
"is_canceled": False,
"issue_datetime": _issue_datetime_1,
"token_status": 1,
"memo": "memo_test1",
- "contract_version": TokenVersion.V_22_12,
+ "contract_version": TokenVersion.V_24_06,
},
{
"issuer_address": issuer_address_1,
@@ -569,11 +580,12 @@ def test_normal_6(self, mock_get, client, db):
"transfer_approval_required": False,
"is_offering": True,
"personal_info_contract_address": "0x1234567890aBcDFE1234567890abcDFE12345679",
+ "require_personal_info_registered": True,
"is_canceled": False,
"issue_datetime": _issue_datetime_2,
"token_status": 0,
"memo": "memo_test2",
- "contract_version": TokenVersion.V_22_12,
+ "contract_version": TokenVersion.V_24_06,
},
]
diff --git a/tests/test_app_routers_share_tokens_POST.py b/tests/app/test_share_tokens_POST.py
similarity index 97%
rename from tests/test_app_routers_share_tokens_POST.py
rename to tests/app/test_share_tokens_POST.py
index 311b34cc..dfde08a5 100644
--- a/tests/test_app_routers_share_tokens_POST.py
+++ b/tests/app/test_share_tokens_POST.py
@@ -20,14 +20,14 @@
import hashlib
import random
import string
-from datetime import datetime, timezone
+from datetime import UTC, datetime
from unittest import mock
from unittest.mock import ANY, patch
import pytest
from sqlalchemy import select
from web3 import Web3
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
import config
from app.exceptions import SendTransactionError
@@ -49,7 +49,7 @@
from tests.account_config import config_eth_account
web3 = Web3(Web3.HTTPProvider(config.WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
class TestAppRoutersShareTokensPOST:
@@ -94,9 +94,7 @@ async def test_normal_1_1(self, client, db):
target="app.utils.contract_utils.AsyncContractUtils.get_block_by_transaction_hash",
return_value={
"number": 12345,
- "timestamp": datetime(
- 2021, 4, 27, 12, 34, 56, tzinfo=timezone.utc
- ).timestamp(),
+ "timestamp": datetime(2021, 4, 27, 12, 34, 56, tzinfo=UTC).timestamp(),
},
)
@@ -168,7 +166,7 @@ async def test_normal_1_1(self, client, db):
assert token_1.token_address == "contract_address_test1"
assert token_1.abi == "abi_test1"
assert token_1.token_status == 1
- assert token_1.version == TokenVersion.V_22_12
+ assert token_1.version == TokenVersion.V_24_06
position = db.scalars(select(IDXPosition).limit(1)).first()
assert position.token_address == "contract_address_test1"
@@ -233,9 +231,7 @@ async def test_normal_1_2(self, client, db):
target="app.utils.contract_utils.AsyncContractUtils.get_block_by_transaction_hash",
return_value={
"number": 12345,
- "timestamp": datetime(
- 2021, 4, 27, 12, 34, 56, tzinfo=timezone.utc
- ).timestamp(),
+ "timestamp": datetime(2021, 4, 27, 12, 34, 56, tzinfo=UTC).timestamp(),
},
)
@@ -292,7 +288,7 @@ async def test_normal_1_2(self, client, db):
assert token_1.token_address == "contract_address_test1"
assert token_1.abi == "abi_test1"
assert token_1.token_status == 1
- assert token_1.version == TokenVersion.V_22_12
+ assert token_1.version == TokenVersion.V_24_06
position = db.scalars(select(IDXPosition).limit(1)).first()
assert position.token_address == "contract_address_test1"
@@ -356,9 +352,7 @@ async def test_normal_2(self, client, db):
target="app.utils.contract_utils.AsyncContractUtils.get_block_by_transaction_hash",
return_value={
"number": 12345,
- "timestamp": datetime(
- 2021, 4, 27, 12, 34, 56, tzinfo=timezone.utc
- ).timestamp(),
+ "timestamp": datetime(2021, 4, 27, 12, 34, 56, tzinfo=UTC).timestamp(),
},
)
@@ -377,6 +371,7 @@ async def test_normal_2(self, client, db):
"cancellation_date": "20221231",
"tradable_exchange_contract_address": "0x0000000000000000000000000000000000000001", # update
"personal_info_contract_address": "0x0000000000000000000000000000000000000002", # update
+ "require_personal_info_registered": False, # update
"transferable": False, # update
"status": False, # update
"is_offering": True, # update
@@ -432,7 +427,7 @@ async def test_normal_2(self, client, db):
assert token_1.token_address == "contract_address_test1"
assert token_1.abi == "abi_test1"
assert token_1.token_status == 0
- assert token_1.version == TokenVersion.V_22_12
+ assert token_1.version == TokenVersion.V_24_06
position = db.scalars(select(IDXPosition).limit(1)).first()
assert position is None
@@ -489,9 +484,7 @@ async def test_normal_3(self, client, db):
target="app.utils.contract_utils.AsyncContractUtils.get_block_by_transaction_hash",
return_value={
"number": 12345,
- "timestamp": datetime(
- 2021, 4, 27, 12, 34, 56, tzinfo=timezone.utc
- ).timestamp(),
+ "timestamp": datetime(2021, 4, 27, 12, 34, 56, tzinfo=UTC).timestamp(),
},
)
@@ -563,7 +556,7 @@ async def test_normal_3(self, client, db):
assert token_1.token_address == "contract_address_test1"
assert token_1.abi == "abi_test1"
assert token_1.token_status == 1
- assert token_1.version == TokenVersion.V_22_12
+ assert token_1.version == TokenVersion.V_24_06
position = db.scalars(select(IDXPosition).limit(1)).first()
assert position.token_address == "contract_address_test1"
@@ -624,9 +617,7 @@ def test_normal_4_1(self, client, db):
target="app.utils.contract_utils.AsyncContractUtils.get_block_by_transaction_hash",
return_value={
"number": 12345,
- "timestamp": datetime(
- 2021, 4, 27, 12, 34, 56, tzinfo=timezone.utc
- ).timestamp(),
+ "timestamp": datetime(2021, 4, 27, 12, 34, 56, tzinfo=UTC).timestamp(),
},
)
@@ -706,9 +697,7 @@ def test_normal_4_2(self, client, db):
target="app.utils.contract_utils.AsyncContractUtils.get_block_by_transaction_hash",
return_value={
"number": 12345,
- "timestamp": datetime(
- 2021, 4, 27, 12, 34, 56, tzinfo=timezone.utc
- ).timestamp(),
+ "timestamp": datetime(2021, 4, 27, 12, 34, 56, tzinfo=UTC).timestamp(),
},
)
diff --git a/tests/test_app_routers_share_tokens_{token_address}_GET.py b/tests/app/test_share_tokens_{token_address}_GET.py
similarity index 94%
rename from tests/test_app_routers_share_tokens_{token_address}_GET.py
rename to tests/app/test_share_tokens_{token_address}_GET.py
index 1efea0b3..7920cc0b 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_GET.py
+++ b/tests/app/test_share_tokens_{token_address}_GET.py
@@ -46,7 +46,7 @@ def test_normal_1(self, mock_get, client, db):
token.issuer_address = "issuer_address_test1"
token.token_address = "token_address_test1"
token.abi = "abi_test1"
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -80,6 +80,7 @@ def test_normal_1(self, mock_get, client, db):
mock_token.personal_info_contract_address = (
"0x1234567890aBcDFE1234567890abcDFE12345679"
)
+ mock_token.require_personal_info_registered = True
mock_token.principal_value = 1000
mock_token.transfer_approval_required = False
mock_token.is_canceled = False
@@ -109,11 +110,12 @@ def test_normal_1(self, mock_get, client, db):
"transfer_approval_required": False,
"is_offering": True,
"personal_info_contract_address": "0x1234567890aBcDFE1234567890abcDFE12345679",
+ "require_personal_info_registered": True,
"is_canceled": False,
"issue_datetime": _issue_time,
"token_status": 1,
"memo": "memo_test1",
- "contract_version": TokenVersion.V_22_12,
+ "contract_version": TokenVersion.V_24_06,
}
assert resp.status_code == 200
@@ -130,7 +132,7 @@ def test_normal_2(self, mock_get, client, db):
token.issuer_address = "issuer_address_test1"
token.token_address = "token_address_test1"
token.abi = "abi_test1"
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -164,6 +166,7 @@ def test_normal_2(self, mock_get, client, db):
mock_token.personal_info_contract_address = (
"0x1234567890aBcDFE1234567890abcDFE12345679"
)
+ mock_token.require_personal_info_registered = True
mock_token.principal_value = 1000
mock_token.transfer_approval_required = False
mock_token.is_canceled = False
@@ -193,11 +196,12 @@ def test_normal_2(self, mock_get, client, db):
"transfer_approval_required": False,
"is_offering": True,
"personal_info_contract_address": "0x1234567890aBcDFE1234567890abcDFE12345679",
+ "require_personal_info_registered": True,
"is_canceled": False,
"issue_datetime": _issue_time,
"token_status": 1,
"memo": "memo_test1",
- "contract_version": TokenVersion.V_22_12,
+ "contract_version": TokenVersion.V_24_06,
}
assert resp.status_code == 200
@@ -229,7 +233,7 @@ def test_error_2(self, client, db):
token.token_address = "token_address_test1"
token.abi = "abi_test1"
token.token_status = 0
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_share_tokens_{token_address}_POST.py b/tests/app/test_share_tokens_{token_address}_POST.py
similarity index 94%
rename from tests/test_app_routers_share_tokens_{token_address}_POST.py
rename to tests/app/test_share_tokens_{token_address}_POST.py
index 2df79157..b3d2a646 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_POST.py
+++ b/tests/app/test_share_tokens_{token_address}_POST.py
@@ -25,7 +25,7 @@
from eth_keyfile import decode_keyfile_json
from sqlalchemy import select
from web3 import Web3
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
import config
from app.exceptions import SendTransactionError
@@ -44,7 +44,7 @@
from tests.account_config import config_eth_account
web3 = Web3(Web3.HTTPProvider(config.WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
async def deploy_share_token_contract(
@@ -108,7 +108,7 @@ async def test_normal_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -121,6 +121,7 @@ async def test_normal_1(self, client, db):
"dividend_payment_date": "20211231",
"tradable_exchange_contract_address": "0xe883A6f441Ad5682d37DF31d34fc012bcB07A740",
"personal_info_contract_address": "0xa4CEe3b909751204AA151860ebBE8E7A851c2A1a",
+ "require_personal_info_registered": False,
"transferable": False,
"status": False,
"is_offering": False,
@@ -168,6 +169,7 @@ async def test_normal_1(self, client, db):
"memo": "",
"name": "token.name",
"personal_info_contract_address": "0x0000000000000000000000000000000000000000",
+ "require_personal_info_registered": True,
"principal_value": 30,
"privacy_policy": "",
"status": True,
@@ -185,6 +187,7 @@ async def test_normal_1(self, client, db):
"dividend_payment_date": "20211231",
"tradable_exchange_contract_address": "0xe883A6f441Ad5682d37DF31d34fc012bcB07A740",
"personal_info_contract_address": "0xa4CEe3b909751204AA151860ebBE8E7A851c2A1a",
+ "require_personal_info_registered": False,
"transferable": False,
"status": False,
"is_offering": False,
@@ -229,7 +232,7 @@ async def test_normal_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -297,7 +300,7 @@ async def test_normal_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -310,6 +313,7 @@ async def test_normal_3(self, client, db):
"dividend_payment_date": "20211231",
"tradable_exchange_contract_address": "0xe883A6f441Ad5682d37DF31d34fc012bcB07A740",
"personal_info_contract_address": "0xa4CEe3b909751204AA151860ebBE8E7A851c2A1a",
+ "require_personal_info_registered": False,
"transferable": False,
"status": False,
"is_offering": False,
@@ -358,6 +362,7 @@ async def test_normal_3(self, client, db):
"memo": "",
"name": "token.name",
"personal_info_contract_address": "0x0000000000000000000000000000000000000000",
+ "require_personal_info_registered": True,
"principal_value": 30,
"privacy_policy": "",
"status": True,
@@ -375,6 +380,7 @@ async def test_normal_3(self, client, db):
"dividend_payment_date": "20211231",
"tradable_exchange_contract_address": "0xe883A6f441Ad5682d37DF31d34fc012bcB07A740",
"personal_info_contract_address": "0xa4CEe3b909751204AA151860ebBE8E7A851c2A1a",
+ "require_personal_info_registered": False,
"transferable": False,
"status": False,
"is_offering": False,
@@ -419,7 +425,7 @@ async def test_normal_4_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -469,6 +475,7 @@ async def test_normal_4_1(self, client, db):
"memo": "",
"name": "token.name",
"personal_info_contract_address": "0x0000000000000000000000000000000000000000",
+ "require_personal_info_registered": True,
"principal_value": 30,
"privacy_policy": "",
"status": True,
@@ -519,7 +526,7 @@ async def test_normal_4_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -569,6 +576,7 @@ async def test_normal_4_2(self, client, db):
"memo": "",
"name": "token.name",
"personal_info_contract_address": "0x0000000000000000000000000000000000000000",
+ "require_personal_info_registered": True,
"principal_value": 30,
"privacy_policy": "",
"status": True,
@@ -1026,7 +1034,7 @@ def test_error_12(self, IbetShareContract_mock, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -1152,7 +1160,7 @@ def test_error_15(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -1200,7 +1208,7 @@ def test_error_16(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -1222,3 +1230,50 @@ def test_error_16(self, client, db):
"meta": {"code": 2, "title": "SendTransactionError"},
"detail": "failed to send transaction",
}
+
+ #
+ # OperationNotSupportedVersionError: v24.6
+ def test_error_17(self, client, db):
+ test_account = config_eth_account("user1")
+ _issuer_address = test_account["address"]
+ _keyfile = test_account["keyfile_json"]
+ _token_address = "0x82b1c9374aB625380bd498a3d9dF4033B8A0E3Bb"
+
+ # prepare data
+ account = Account()
+ account.issuer_address = _issuer_address
+ account.keyfile = _keyfile
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ token = Token()
+ token.type = TokenType.IBET_SHARE.value
+ token.tx_hash = ""
+ token.issuer_address = _issuer_address
+ token.token_address = _token_address
+ token.abi = ""
+ token.token_status = 1
+ token.version = TokenVersion.V_22_12
+ db.add(token)
+
+ db.commit()
+
+ # request target API
+ req_param = {
+ "require_personal_info_registered": False,
+ }
+ resp = client.post(
+ self.base_url.format(_token_address),
+ json=req_param,
+ headers={
+ "issuer-address": _issuer_address,
+ "eoa-password": E2EEUtils.encrypt("password"),
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 400
+ assert resp.json() == {
+ "meta": {"code": 6, "title": "OperationNotSupportedVersionError"},
+ "detail": "the operation is not supported in 22_12",
+ }
diff --git a/tests/test_app_routers_share_tokens_{token_address}_additional_issue_GET.py b/tests/app/test_share_tokens_{token_address}_additional_issue_GET.py
similarity index 98%
rename from tests/test_app_routers_share_tokens_{token_address}_additional_issue_GET.py
rename to tests/app/test_share_tokens_{token_address}_additional_issue_GET.py
index f1b13267..0047fbd8 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_additional_issue_GET.py
+++ b/tests/app/test_share_tokens_{token_address}_additional_issue_GET.py
@@ -74,7 +74,7 @@ def test_normal_1(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXIssueRedeem
@@ -110,7 +110,7 @@ def test_normal_2(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXIssueRedeem
@@ -191,7 +191,7 @@ def test_normal_3(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXIssueRedeem
@@ -278,7 +278,7 @@ def test_normal_4(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXIssueRedeem
@@ -365,7 +365,7 @@ def test_error_2(self, client, db):
_token.token_address = self.test_token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -425,7 +425,7 @@ def test_error_4_1(self, client, db):
"detail": [
{
"ctx": {"expected": "0 or 1"},
- "input": -1,
+ "input": "-1",
"loc": ["query", "sort_order"],
"msg": "Input should be 0 or 1",
"type": "enum",
@@ -449,7 +449,7 @@ def test_error_4_2(self, client, db):
"detail": [
{
"ctx": {"expected": "0 or 1"},
- "input": 2,
+ "input": "2",
"loc": ["query", "sort_order"],
"msg": "Input should be 0 or 1",
"type": "enum",
diff --git a/tests/test_app_routers_share_tokens_{token_address}_additional_issue_POST.py b/tests/app/test_share_tokens_{token_address}_additional_issue_POST.py
similarity index 98%
rename from tests/test_app_routers_share_tokens_{token_address}_additional_issue_POST.py
rename to tests/app/test_share_tokens_{token_address}_additional_issue_POST.py
index 495dfba6..988379ee 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_additional_issue_POST.py
+++ b/tests/app/test_share_tokens_{token_address}_additional_issue_POST.py
@@ -58,7 +58,7 @@ def test_normal_1(self, IbetShareContract_mock, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -115,7 +115,7 @@ def test_normal_2(self, IbetShareContract_mock, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -287,7 +287,7 @@ def test_error_5(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -330,7 +330,7 @@ def test_error_6(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -444,7 +444,7 @@ def test_error_9(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -492,7 +492,7 @@ def test_error_10(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_share_tokens_{token_address}_additional_issue_batch_GET.py b/tests/app/test_share_tokens_{token_address}_additional_issue_batch_GET.py
similarity index 98%
rename from tests/test_app_routers_share_tokens_{token_address}_additional_issue_batch_GET.py
rename to tests/app/test_share_tokens_{token_address}_additional_issue_batch_GET.py
index 838867b9..0208037c 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_additional_issue_batch_GET.py
+++ b/tests/app/test_share_tokens_{token_address}_additional_issue_batch_GET.py
@@ -52,7 +52,7 @@ def test_normal_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -80,7 +80,7 @@ def test_normal_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
additional_issue_upload1 = BatchIssueRedeemUpload()
@@ -129,7 +129,7 @@ def test_normal_3_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
additional_issue_upload1 = BatchIssueRedeemUpload()
@@ -246,7 +246,7 @@ def test_normal_3_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
additional_issue_upload1 = BatchIssueRedeemUpload()
@@ -350,7 +350,7 @@ def test_normal_3_3(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
additional_issue_upload1 = BatchIssueRedeemUpload()
@@ -460,7 +460,7 @@ def test_normal_4(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
additional_issue_upload1 = BatchIssueRedeemUpload()
@@ -562,7 +562,7 @@ def test_normal_5(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
additional_issue_upload1 = BatchIssueRedeemUpload()
@@ -685,7 +685,7 @@ def test_error_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_share_tokens_{token_address}_additional_issue_batch_POST.py b/tests/app/test_share_tokens_{token_address}_additional_issue_batch_POST.py
similarity index 97%
rename from tests/test_app_routers_share_tokens_{token_address}_additional_issue_batch_POST.py
rename to tests/app/test_share_tokens_{token_address}_additional_issue_batch_POST.py
index acd9f681..edd7c9c0 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_additional_issue_batch_POST.py
+++ b/tests/app/test_share_tokens_{token_address}_additional_issue_batch_POST.py
@@ -66,7 +66,7 @@ def test_normal_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -131,7 +131,7 @@ def test_normal_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -206,7 +206,7 @@ def test_error_1_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -258,7 +258,7 @@ def test_error_1_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -313,7 +313,7 @@ def test_error_1_3_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -368,7 +368,7 @@ def test_error_1_3_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -423,7 +423,7 @@ def test_error_1_4(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -472,7 +472,7 @@ def test_error_1_5(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -521,7 +521,7 @@ def test_error_1_6(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -568,7 +568,7 @@ def test_error_1_7_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -615,7 +615,7 @@ def test_error_1_7_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -703,7 +703,7 @@ def test_error_1_8_2(self, client, db):
token.token_address = token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_share_tokens_{token_address}_additional_issue_batch_{batch_id}_GET.py b/tests/app/test_share_tokens_{token_address}_additional_issue_batch_{batch_id}_GET.py
similarity index 98%
rename from tests/test_app_routers_share_tokens_{token_address}_additional_issue_batch_{batch_id}_GET.py
rename to tests/app/test_share_tokens_{token_address}_additional_issue_batch_{batch_id}_GET.py
index 95d790d4..a6618700 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_additional_issue_batch_{batch_id}_GET.py
+++ b/tests/app/test_share_tokens_{token_address}_additional_issue_batch_{batch_id}_GET.py
@@ -71,7 +71,7 @@ def test_normal_1_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = test_token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
batch_upload = BatchIssueRedeemUpload()
@@ -158,7 +158,7 @@ def test_normal_1_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = test_token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
batch_upload = BatchIssueRedeemUpload()
@@ -245,7 +245,7 @@ def test_normal_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = test_token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
batch_upload = BatchIssueRedeemUpload()
@@ -358,7 +358,7 @@ def test_error_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = test_token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
batch_upload = BatchIssueRedeemUpload()
diff --git a/tests/test_app_routers_share_tokens_{token_address}_history_GET.py b/tests/app/test_share_tokens_{token_address}_history_GET.py
similarity index 96%
rename from tests/test_app_routers_share_tokens_{token_address}_history_GET.py
rename to tests/app/test_share_tokens_{token_address}_history_GET.py
index 2bfd869b..ebc695ec 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_history_GET.py
+++ b/tests/app/test_share_tokens_{token_address}_history_GET.py
@@ -27,7 +27,7 @@
from starlette.testclient import TestClient
from web3 import Web3
from web3.contract import Contract
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
import config
from app.model.blockchain import IbetShareContract
@@ -45,7 +45,7 @@
from tests.account_config import config_eth_account
web3 = Web3(Web3.HTTPProvider(config.WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
async def deploy_share_token_contract(
@@ -87,6 +87,7 @@ async def deploy_share_token_contract(
is_offering=True, # update
tradable_exchange_contract_address=tradable_exchange_contract_address, # update
personal_info_contract_address=personal_info_contract_address, # update
+ require_personal_info_registered=False, # update
contact_information="contact info test", # update
privacy_policy="privacy policy test", # update
transfer_approval_required=transfer_approval_required, # update
@@ -135,6 +136,10 @@ async def deploy_share_token_contract(
token_create_param["personal_info_contract_address"]
).build_transaction(build_tx_param)
ContractUtils.send_transaction(transaction=tx, private_key=private_key)
+ tx = contract.functions.setRequirePersonalInfoRegistered(
+ token_create_param["require_personal_info_registered"]
+ ).build_transaction(build_tx_param)
+ ContractUtils.send_transaction(transaction=tx, private_key=private_key)
tx = contract.functions.setContactInformation(
token_create_param["contact_information"]
).build_transaction(build_tx_param)
@@ -232,7 +237,7 @@ def test_normal_1(self, client, db, personal_info_contract):
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -285,7 +290,7 @@ async def test_normal_2(self, client, db, personal_info_contract):
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -388,7 +393,7 @@ async def test_normal_3_1(self, client, db, personal_info_contract):
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -489,7 +494,7 @@ async def test_normal_3_2(self, client, db, personal_info_contract):
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -577,7 +582,7 @@ async def test_normal_3_3(self, client, db, personal_info_contract):
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_operation_log_1 = TokenUpdateOperationLog()
@@ -617,7 +622,7 @@ async def test_normal_3_3(self, client, db, personal_info_contract):
resp = client.get(
self.base_url.format(_token_address),
params={
- "created_from": str(datetime(2023, 5, 3, 8, 0, 0)),
+ "created_from": "2023-05-03 08:00:00",
},
)
@@ -635,13 +640,13 @@ async def test_normal_3_3(self, client, db, personal_info_contract):
"original_contents": {},
"modified_contents": {"memo": "20230504"},
"operation_category": TokenUpdateOperationCategory.UPDATE.value,
- "created": ANY,
+ "created": "2023-05-04T09:00:00+09:00",
},
{
"original_contents": {},
"modified_contents": {"memo": "20230503"},
"operation_category": TokenUpdateOperationCategory.UPDATE.value,
- "created": ANY,
+ "created": "2023-05-03T09:00:00+09:00",
},
],
}
@@ -681,7 +686,7 @@ async def test_normal_3_4(self, client, db, personal_info_contract):
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
_operation_log_1 = TokenUpdateOperationLog()
@@ -723,7 +728,7 @@ async def test_normal_3_4(self, client, db, personal_info_contract):
resp = client.get(
self.base_url.format(_token_address),
params={
- "created_to": str(datetime(2023, 5, 2, 0, 0, 0)),
+ "created_to": "2023-05-02 00:00:00",
},
)
@@ -741,7 +746,7 @@ async def test_normal_3_4(self, client, db, personal_info_contract):
"original_contents": None,
"modified_contents": create_param,
"operation_category": TokenUpdateOperationCategory.ISSUE.value,
- "created": ANY,
+ "created": "2023-05-01T09:00:00+09:00",
},
],
}
@@ -777,7 +782,7 @@ async def test_normal_4_1(self, client, db, personal_info_contract):
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -884,7 +889,7 @@ async def test_normal_4_2(self, client, db, personal_info_contract):
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -992,7 +997,7 @@ async def test_normal_5_1(self, client, db, personal_info_contract):
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -1080,7 +1085,7 @@ async def test_normal_5_2(self, client, db, personal_info_contract):
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -1137,39 +1142,37 @@ def test_error_1(self, client, db):
"meta": {"code": 1, "title": "RequestValidationError"},
"detail": [
{
- "ctx": {"expected": "'Issue' or 'Update'"},
- "input": "test",
+ "type": "enum",
"loc": ["query", "operation_category"],
"msg": "Input should be 'Issue' or 'Update'",
- "type": "enum",
+ "input": "test",
+ "ctx": {"expected": "'Issue' or 'Update'"},
},
{
- "ctx": {"expected": "'created' or 'operation_category'"},
- "input": "test",
+ "type": "enum",
"loc": ["query", "sort_item"],
"msg": "Input should be 'created' or 'operation_category'",
- "type": "enum",
+ "input": "test",
+ "ctx": {"expected": "'created' or 'operation_category'"},
},
{
- "input": "test",
+ "type": "enum",
"loc": ["query", "sort_order"],
- "msg": "Input should be a valid integer, unable to parse string "
- "as an integer",
- "type": "int_parsing",
+ "msg": "Input should be 0 or 1",
+ "input": "test",
+ "ctx": {"expected": "0 or 1"},
},
{
- "input": "test",
- "loc": ["query", "offset"],
- "msg": "Input should be a valid integer, unable to parse string "
- "as an integer",
"type": "int_parsing",
+ "loc": ["query", "offset"],
+ "msg": "Input should be a valid integer, unable to parse string as an integer",
+ "input": "test",
},
{
- "input": "test",
- "loc": ["query", "limit"],
- "msg": "Input should be a valid integer, unable to parse string "
- "as an integer",
"type": "int_parsing",
+ "loc": ["query", "limit"],
+ "msg": "Input should be a valid integer, unable to parse string as an integer",
+ "input": "test",
},
],
}
diff --git a/tests/test_app_routers_share_tokens_{token_address}_holders_GET.py b/tests/app/test_share_tokens_{token_address}_holders_GET.py
similarity index 85%
rename from tests/test_app_routers_share_tokens_{token_address}_holders_GET.py
rename to tests/app/test_share_tokens_{token_address}_holders_GET.py
index 760a74e6..88a167be 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_holders_GET.py
+++ b/tests/app/test_share_tokens_{token_address}_holders_GET.py
@@ -57,7 +57,7 @@ def test_normal_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -95,7 +95,7 @@ def test_normal_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: Position
@@ -212,7 +212,7 @@ def test_normal_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -441,7 +441,7 @@ def test_normal_4_1_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -590,7 +590,7 @@ def test_normal_4_1_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
idx_position_1 = IDXPosition()
@@ -747,7 +747,7 @@ def test_normal_4_2_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -939,7 +939,7 @@ def test_normal_4_2_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -1150,7 +1150,7 @@ def test_normal_4_2_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -1361,7 +1361,7 @@ def test_normal_4_3_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -1553,7 +1553,7 @@ def test_normal_4_3_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -1764,7 +1764,7 @@ def test_normal_4_3_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -1975,7 +1975,7 @@ def test_normal_4_4_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -2167,7 +2167,7 @@ def test_normal_4_4_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -2367,6 +2367,7 @@ def test_normal_4_4_3(self, client, db):
_account_address_1 = "0xb75c7545b9230FEe99b7af370D38eBd3DAD929f7"
_account_address_2 = "0x3F198534Bbe3B2a197d3B317d41392F348EAC707"
_account_address_3 = "0x8277D905F37F8a9717F5718d0daC21495dFE74bf"
+ _account_address_4 = "0x1CBd3b2770909D4e10f157cABC84C7264073C9Ec"
account = Account()
account.issuer_address = _issuer_address
@@ -2378,7 +2379,657 @@ def test_normal_4_4_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ # prepare data: account_address_1
+ idx_position_1 = IDXPosition()
+ idx_position_1.token_address = _token_address
+ idx_position_1.account_address = _account_address_1
+ idx_position_1.balance = 10
+ idx_position_1.exchange_balance = 11
+ idx_position_1.exchange_commitment = 12
+ idx_position_1.pending_transfer = 5
+ idx_position_1.modified = datetime(2023, 10, 24, 0, 0, 0)
+ db.add(idx_position_1)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_1
+ idx_locked_position.value = 5
+ idx_locked_position.modified = datetime(2023, 10, 24, 1, 0, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_1
+ idx_locked_position.value = 5
+ idx_locked_position.modified = datetime(2023, 10, 24, 1, 10, 0)
+ db.add(idx_locked_position)
+
+ idx_personal_info_1 = IDXPersonalInfo()
+ idx_personal_info_1.account_address = _account_address_1
+ idx_personal_info_1.issuer_address = _issuer_address
+ idx_personal_info_1.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ db.add(idx_personal_info_1)
+
+ # prepare data: account_address_2
+ idx_position_2 = IDXPosition()
+ idx_position_2.token_address = _token_address
+ idx_position_2.account_address = _account_address_2
+ idx_position_2.balance = 20
+ idx_position_2.exchange_balance = 21
+ idx_position_2.exchange_commitment = 22
+ idx_position_2.pending_transfer = 10
+ idx_position_2.modified = datetime(2023, 10, 24, 2, 0, 0)
+ db.add(idx_position_2)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_2
+ idx_locked_position.value = 10
+ idx_locked_position.modified = datetime(2023, 10, 24, 2, 10, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_2
+ idx_locked_position.value = 10
+ idx_locked_position.modified = datetime(2023, 10, 24, 2, 20, 0)
+ db.add(idx_locked_position)
+
+ # prepare data: account_address_3
+ idx_position_3 = IDXPosition()
+ idx_position_3.token_address = _token_address
+ idx_position_3.account_address = _account_address_3
+ idx_position_3.balance = 99
+ idx_position_3.exchange_balance = 99
+ idx_position_3.exchange_commitment = 99
+ idx_position_3.pending_transfer = 99
+ idx_position_3.modified = datetime(2023, 10, 24, 3, 0, 0)
+ db.add(idx_position_3)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_3
+ idx_locked_position.value = 15
+ idx_locked_position.modified = datetime(2023, 10, 24, 4, 0, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_3
+ idx_locked_position.value = 15
+ idx_locked_position.modified = datetime(2023, 10, 24, 5, 0, 0)
+ db.add(idx_locked_position)
+
+ # Other locked position
+ _locked_position = IDXLockedPosition()
+ _locked_position.token_address = "other_token_address"
+ _locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ _locked_position.account_address = _account_address_1
+ _locked_position.value = 5
+ _locked_position.modified = datetime(2023, 10, 25, 0, 2, 0)
+ db.add(_locked_position)
+
+ idx_personal_info_3 = IDXPersonalInfo()
+ idx_personal_info_3.account_address = _account_address_3
+ idx_personal_info_3.issuer_address = _issuer_address
+ idx_personal_info_3.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": "birth_test3",
+ # PersonalInfo is partially registered.
+ }
+ db.add(idx_personal_info_3)
+
+ # prepare data: account_address_4
+ idx_position_4 = IDXPosition()
+ idx_position_4.token_address = _token_address
+ idx_position_4.account_address = _account_address_4
+ idx_position_4.balance = 99
+ idx_position_4.exchange_balance = 99
+ idx_position_4.exchange_commitment = 99
+ idx_position_4.pending_transfer = 99
+ idx_position_4.modified = datetime(2023, 10, 24, 3, 0, 0)
+ db.add(idx_position_4)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(_token_address),
+ headers={"issuer-address": _issuer_address},
+ params={"locked": 20, "locked_operator": 2},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 3, "limit": None, "offset": None, "total": 4},
+ "holders": [
+ {
+ "account_address": _account_address_1,
+ "personal_information": {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "balance": 10,
+ "exchange_balance": 11,
+ "exchange_commitment": 12,
+ "pending_transfer": 5,
+ "locked": 10,
+ "modified": "2023-10-24T01:10:00",
+ },
+ {
+ "account_address": _account_address_2,
+ "personal_information": {
+ "key_manager": None,
+ "name": None,
+ "postal_code": None,
+ "address": None,
+ "email": None,
+ "birth": None,
+ "is_corporate": None,
+ "tax_category": None,
+ },
+ "balance": 20,
+ "exchange_balance": 21,
+ "exchange_commitment": 22,
+ "pending_transfer": 10,
+ "locked": 20,
+ "modified": "2023-10-24T02:20:00",
+ },
+ {
+ "account_address": _account_address_4,
+ "pending_transfer": 99,
+ "personal_information": {
+ "address": None,
+ "birth": None,
+ "email": None,
+ "is_corporate": None,
+ "key_manager": None,
+ "name": None,
+ "postal_code": None,
+ "tax_category": None,
+ },
+ "balance": 99,
+ "exchange_balance": 99,
+ "exchange_commitment": 99,
+ "locked": 0,
+ "modified": "2023-10-24T03:00:00",
+ },
+ ],
+ }
+
+ #
+ # Search filter: balance + pending_transfer & "="
+ def test_normal_4_5_1(self, client, db):
+ user = config_eth_account("user1")
+ _issuer_address = user["address"]
+ _token_address = "0x82b1c9374aB625380bd498a3d9dF4033B8A0E3Bb"
+ _account_address_1 = "0xb75c7545b9230FEe99b7af370D38eBd3DAD929f7"
+ _account_address_2 = "0x3F198534Bbe3B2a197d3B317d41392F348EAC707"
+ _account_address_3 = "0x8277D905F37F8a9717F5718d0daC21495dFE74bf"
+
+ account = Account()
+ account.issuer_address = _issuer_address
+ db.add(account)
+
+ token = Token()
+ token.type = TokenType.IBET_SHARE.value
+ token.tx_hash = ""
+ token.issuer_address = _issuer_address
+ token.token_address = _token_address
+ token.abi = ""
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ # prepare data: account_address_1
+ idx_position_1 = IDXPosition()
+ idx_position_1.token_address = _token_address
+ idx_position_1.account_address = _account_address_1
+ idx_position_1.balance = 10
+ idx_position_1.exchange_balance = 11
+ idx_position_1.exchange_commitment = 12
+ idx_position_1.pending_transfer = 5
+ idx_position_1.modified = datetime(2023, 10, 24, 0, 0, 0)
+ db.add(idx_position_1)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_1
+ idx_locked_position.value = 5
+ idx_locked_position.modified = datetime(2023, 10, 24, 1, 0, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_1
+ idx_locked_position.value = 5
+ idx_locked_position.modified = datetime(2023, 10, 24, 1, 10, 0)
+ db.add(idx_locked_position)
+
+ idx_personal_info_1 = IDXPersonalInfo()
+ idx_personal_info_1.account_address = _account_address_1
+ idx_personal_info_1.issuer_address = _issuer_address
+ idx_personal_info_1.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ db.add(idx_personal_info_1)
+
+ # prepare data: account_address_2
+ idx_position_2 = IDXPosition()
+ idx_position_2.token_address = _token_address
+ idx_position_2.account_address = _account_address_2
+ idx_position_2.balance = 20
+ idx_position_2.exchange_balance = 21
+ idx_position_2.exchange_commitment = 22
+ idx_position_2.pending_transfer = 10
+ idx_position_2.modified = datetime(2023, 10, 24, 2, 0, 0)
+ db.add(idx_position_2)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_2
+ idx_locked_position.value = 10
+ idx_locked_position.modified = datetime(2023, 10, 24, 2, 10, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_2
+ idx_locked_position.value = 10
+ idx_locked_position.modified = datetime(2023, 10, 24, 2, 20, 0)
+ db.add(idx_locked_position)
+
+ # prepare data: account_address_3
+ idx_position_3 = IDXPosition()
+ idx_position_3.token_address = _token_address
+ idx_position_3.account_address = _account_address_3
+ idx_position_3.balance = 99
+ idx_position_3.exchange_balance = 99
+ idx_position_3.exchange_commitment = 99
+ idx_position_3.pending_transfer = 99
+ idx_position_3.modified = datetime(2023, 10, 24, 3, 0, 0)
+ db.add(idx_position_3)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_3
+ idx_locked_position.value = 15
+ idx_locked_position.modified = datetime(2023, 10, 24, 4, 0, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_3
+ idx_locked_position.value = 15
+ idx_locked_position.modified = datetime(2023, 10, 24, 5, 0, 0)
+ db.add(idx_locked_position)
+
+ # Other locked position
+ _locked_position = IDXLockedPosition()
+ _locked_position.token_address = "other_token_address"
+ _locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ _locked_position.account_address = _account_address_1
+ _locked_position.value = 5
+ _locked_position.modified = datetime(2023, 10, 25, 0, 2, 0)
+ db.add(_locked_position)
+
+ idx_personal_info_3 = IDXPersonalInfo()
+ idx_personal_info_3.account_address = _account_address_3
+ idx_personal_info_3.issuer_address = _issuer_address
+ idx_personal_info_3.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": "birth_test3",
+ # PersonalInfo is partially registered.
+ }
+ db.add(idx_personal_info_3)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(_token_address),
+ headers={"issuer-address": _issuer_address},
+ params={
+ "balance_and_pending_transfer": 30,
+ "balance_and_pending_transfer_operator": 0,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 1, "total": 3, "offset": None, "limit": None},
+ "holders": [
+ {
+ "account_address": _account_address_2,
+ "personal_information": {
+ "key_manager": None,
+ "name": None,
+ "postal_code": None,
+ "address": None,
+ "email": None,
+ "birth": None,
+ "is_corporate": None,
+ "tax_category": None,
+ },
+ "balance": 20,
+ "exchange_balance": 21,
+ "exchange_commitment": 22,
+ "pending_transfer": 10,
+ "locked": 20,
+ "modified": "2023-10-24T02:20:00",
+ },
+ ],
+ }
+
+ #
+ # Search filter: balance + pending_transfer & ">="
+ def test_normal_4_5_2(self, client, db):
+ user = config_eth_account("user1")
+ _issuer_address = user["address"]
+ _token_address = "0x82b1c9374aB625380bd498a3d9dF4033B8A0E3Bb"
+ _account_address_1 = "0xb75c7545b9230FEe99b7af370D38eBd3DAD929f7"
+ _account_address_2 = "0x3F198534Bbe3B2a197d3B317d41392F348EAC707"
+ _account_address_3 = "0x8277D905F37F8a9717F5718d0daC21495dFE74bf"
+
+ account = Account()
+ account.issuer_address = _issuer_address
+ db.add(account)
+
+ token = Token()
+ token.type = TokenType.IBET_SHARE.value
+ token.tx_hash = ""
+ token.issuer_address = _issuer_address
+ token.token_address = _token_address
+ token.abi = ""
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ # prepare data: account_address_1
+ idx_position_1 = IDXPosition()
+ idx_position_1.token_address = _token_address
+ idx_position_1.account_address = _account_address_1
+ idx_position_1.balance = 10
+ idx_position_1.exchange_balance = 11
+ idx_position_1.exchange_commitment = 12
+ idx_position_1.pending_transfer = 5
+ idx_position_1.modified = datetime(2023, 10, 24, 0, 0, 0)
+ db.add(idx_position_1)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_1
+ idx_locked_position.value = 5
+ idx_locked_position.modified = datetime(2023, 10, 24, 1, 0, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_1
+ idx_locked_position.value = 5
+ idx_locked_position.modified = datetime(2023, 10, 24, 1, 10, 0)
+ db.add(idx_locked_position)
+
+ idx_personal_info_1 = IDXPersonalInfo()
+ idx_personal_info_1.account_address = _account_address_1
+ idx_personal_info_1.issuer_address = _issuer_address
+ idx_personal_info_1.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ db.add(idx_personal_info_1)
+
+ # prepare data: account_address_2
+ idx_position_2 = IDXPosition()
+ idx_position_2.token_address = _token_address
+ idx_position_2.account_address = _account_address_2
+ idx_position_2.balance = 20
+ idx_position_2.exchange_balance = 21
+ idx_position_2.exchange_commitment = 22
+ idx_position_2.pending_transfer = 10
+ idx_position_2.modified = datetime(2023, 10, 24, 2, 0, 0)
+ db.add(idx_position_2)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_2
+ idx_locked_position.value = 10
+ idx_locked_position.modified = datetime(2023, 10, 24, 2, 10, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_2
+ idx_locked_position.value = 10
+ idx_locked_position.modified = datetime(2023, 10, 24, 2, 20, 0)
+ db.add(idx_locked_position)
+
+ # prepare data: account_address_3
+ idx_position_3 = IDXPosition()
+ idx_position_3.token_address = _token_address
+ idx_position_3.account_address = _account_address_3
+ idx_position_3.balance = 99
+ idx_position_3.exchange_balance = 99
+ idx_position_3.exchange_commitment = 99
+ idx_position_3.pending_transfer = 99
+ idx_position_3.modified = datetime(2023, 10, 24, 3, 0, 0)
+ db.add(idx_position_3)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_3
+ idx_locked_position.value = 15
+ idx_locked_position.modified = datetime(2023, 10, 24, 4, 0, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_3
+ idx_locked_position.value = 15
+ idx_locked_position.modified = datetime(2023, 10, 24, 5, 0, 0)
+ db.add(idx_locked_position)
+
+ # Other locked position
+ _locked_position = IDXLockedPosition()
+ _locked_position.token_address = "other_token_address"
+ _locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ _locked_position.account_address = _account_address_1
+ _locked_position.value = 5
+ _locked_position.modified = datetime(2023, 10, 25, 0, 2, 0)
+ db.add(_locked_position)
+
+ idx_personal_info_3 = IDXPersonalInfo()
+ idx_personal_info_3.account_address = _account_address_3
+ idx_personal_info_3.issuer_address = _issuer_address
+ idx_personal_info_3.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": "birth_test3",
+ # PersonalInfo is partially registered.
+ }
+ db.add(idx_personal_info_3)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(_token_address),
+ headers={"issuer-address": _issuer_address},
+ params={
+ "balance_and_pending_transfer": 30,
+ "balance_and_pending_transfer_operator": 1,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 2, "total": 3, "offset": None, "limit": None},
+ "holders": [
+ {
+ "account_address": _account_address_2,
+ "personal_information": {
+ "key_manager": None,
+ "name": None,
+ "postal_code": None,
+ "address": None,
+ "email": None,
+ "birth": None,
+ "is_corporate": None,
+ "tax_category": None,
+ },
+ "balance": 20,
+ "exchange_balance": 21,
+ "exchange_commitment": 22,
+ "pending_transfer": 10,
+ "locked": 20,
+ "modified": "2023-10-24T02:20:00",
+ },
+ {
+ "account_address": _account_address_3,
+ "personal_information": {
+ "key_manager": "key_manager_test1",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": "birth_test3",
+ "is_corporate": None,
+ "tax_category": None,
+ },
+ "balance": 99,
+ "exchange_balance": 99,
+ "exchange_commitment": 99,
+ "pending_transfer": 99,
+ "locked": 30,
+ "modified": "2023-10-24T05:00:00",
+ },
+ ],
+ }
+
+ #
+ # Search filter: balance + pending_transfer & "<="
+ def test_normal_4_5_3(self, client, db):
+ user = config_eth_account("user1")
+ _issuer_address = user["address"]
+ _token_address = "0x82b1c9374aB625380bd498a3d9dF4033B8A0E3Bb"
+ _account_address_1 = "0xb75c7545b9230FEe99b7af370D38eBd3DAD929f7"
+ _account_address_2 = "0x3F198534Bbe3B2a197d3B317d41392F348EAC707"
+ _account_address_3 = "0x8277D905F37F8a9717F5718d0daC21495dFE74bf"
+
+ account = Account()
+ account.issuer_address = _issuer_address
+ db.add(account)
+
+ token = Token()
+ token.type = TokenType.IBET_SHARE.value
+ token.tx_hash = ""
+ token.issuer_address = _issuer_address
+ token.token_address = _token_address
+ token.abi = ""
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -2520,7 +3171,10 @@ def test_normal_4_4_3(self, client, db):
resp = client.get(
self.base_url.format(_token_address),
headers={"issuer-address": _issuer_address},
- params={"locked": 20, "locked_operator": 2},
+ params={
+ "balance_and_pending_transfer": 30,
+ "balance_and_pending_transfer_operator": 2,
+ },
)
# assertion
@@ -2569,9 +3223,9 @@ def test_normal_4_4_3(self, client, db):
],
}
- #
+ #
# Search filter: holder_name
- def test_normal_4_5(self, client, db):
+ def test_normal_4_6(self, client, db):
user = config_eth_account("user1")
_issuer_address = user["address"]
_token_address = "0x82b1c9374aB625380bd498a3d9dF4033B8A0E3Bb"
@@ -2589,7 +3243,7 @@ def test_normal_4_5(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -2761,9 +3415,9 @@ def test_normal_4_5(self, client, db):
],
}
- #
+ #
# Search filter: key_manager
- def test_normal_4_6(self, client, db):
+ def test_normal_4_7(self, client, db):
user = config_eth_account("user1")
_issuer_address = user["address"]
_token_address = "0x82b1c9374aB625380bd498a3d9dF4033B8A0E3Bb"
@@ -2781,7 +3435,7 @@ def test_normal_4_6(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -2972,9 +3626,9 @@ def test_normal_4_6(self, client, db):
],
}
- #
+ #
# Search filter: account_address
- def test_normal_4_7(self, client, db):
+ def test_normal_4_8(self, client, db):
user = config_eth_account("user1")
_issuer_address = user["address"]
_token_address = "0x82b1c9374aB625380bd498a3d9dF4033B8A0E3Bb"
@@ -2992,7 +3646,7 @@ def test_normal_4_7(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -3184,7 +3838,7 @@ def test_normal_5_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -3417,7 +4071,7 @@ def test_normal_5_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -3650,7 +4304,7 @@ def test_normal_5_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -3883,7 +4537,7 @@ def test_normal_5_4(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -4116,7 +4770,7 @@ def test_normal_5_5(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -4330,7 +4984,7 @@ def test_normal_5_5(self, client, db):
}
#
- # Sort Item: holder_name
+ # Sort Item: balance + pending_transfer
def test_normal_5_6(self, client, db):
user = config_eth_account("user1")
_issuer_address = user["address"]
@@ -4338,6 +4992,239 @@ def test_normal_5_6(self, client, db):
_account_address_1 = "0xb75c7545b9230FEe99b7af370D38eBd3DAD929f7"
_account_address_2 = "0x3F198534Bbe3B2a197d3B317d41392F348EAC707"
_account_address_3 = "0x8277D905F37F8a9717F5718d0daC21495dFE74bf"
+
+ account = Account()
+ account.issuer_address = _issuer_address
+ db.add(account)
+
+ token = Token()
+ token.type = TokenType.IBET_SHARE.value
+ token.tx_hash = ""
+ token.issuer_address = _issuer_address
+ token.token_address = _token_address
+ token.abi = ""
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ # prepare data: account_address_1
+ idx_position_1 = IDXPosition()
+ idx_position_1.token_address = _token_address
+ idx_position_1.account_address = _account_address_1
+ idx_position_1.balance = 10
+ idx_position_1.exchange_balance = 11
+ idx_position_1.exchange_commitment = 12
+ idx_position_1.pending_transfer = 5
+ idx_position_1.created = datetime(2023, 10, 24, 0, 0, 0)
+ idx_position_1.modified = datetime(2023, 10, 24, 0, 0, 0)
+ db.add(idx_position_1)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_1
+ idx_locked_position.value = 5
+ idx_locked_position.modified = datetime(2023, 10, 24, 1, 0, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_1
+ idx_locked_position.value = 5
+ idx_locked_position.modified = datetime(2023, 10, 24, 1, 10, 0)
+ db.add(idx_locked_position)
+
+ idx_personal_info_1 = IDXPersonalInfo()
+ idx_personal_info_1.account_address = _account_address_1
+ idx_personal_info_1.issuer_address = _issuer_address
+ idx_personal_info_1.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ db.add(idx_personal_info_1)
+
+ # prepare data: account_address_2
+ idx_position_2 = IDXPosition()
+ idx_position_2.token_address = _token_address
+ idx_position_2.account_address = _account_address_2
+ idx_position_2.balance = 20
+ idx_position_2.exchange_balance = 21
+ idx_position_2.exchange_commitment = 22
+ idx_position_2.pending_transfer = 10
+ idx_position_2.created = datetime(2023, 10, 24, 2, 0, 0)
+ idx_position_2.modified = datetime(2023, 10, 24, 2, 0, 0)
+ db.add(idx_position_2)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_2
+ idx_locked_position.value = 10
+ idx_locked_position.modified = datetime(2023, 10, 24, 2, 10, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_2
+ idx_locked_position.value = 10
+ idx_locked_position.modified = datetime(2023, 10, 24, 2, 20, 0)
+ db.add(idx_locked_position)
+
+ # prepare data: account_address_3
+ idx_position_3 = IDXPosition()
+ idx_position_3.token_address = _token_address
+ idx_position_3.account_address = _account_address_3
+ idx_position_3.balance = 99
+ idx_position_3.exchange_balance = 99
+ idx_position_3.exchange_commitment = 99
+ idx_position_3.pending_transfer = 99
+ idx_position_3.created = datetime(2023, 10, 24, 3, 0, 0)
+ idx_position_3.modified = datetime(2023, 10, 24, 3, 0, 0)
+ db.add(idx_position_3)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000001" # lock address 1
+ )
+ idx_locked_position.account_address = _account_address_3
+ idx_locked_position.value = 15
+ idx_locked_position.modified = datetime(2023, 10, 24, 4, 0, 0)
+ db.add(idx_locked_position)
+
+ idx_locked_position = IDXLockedPosition()
+ idx_locked_position.token_address = _token_address
+ idx_locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ idx_locked_position.account_address = _account_address_3
+ idx_locked_position.value = 15
+ idx_locked_position.modified = datetime(2023, 10, 24, 5, 0, 0)
+ db.add(idx_locked_position)
+
+ # Other locked position
+ _locked_position = IDXLockedPosition()
+ _locked_position.token_address = "other_token_address"
+ _locked_position.lock_address = (
+ "0x1234567890123456789012345678900000000002" # lock address 2
+ )
+ _locked_position.account_address = _account_address_1
+ _locked_position.value = 5
+ _locked_position.modified = datetime(2023, 10, 25, 0, 2, 0)
+ db.add(_locked_position)
+
+ idx_personal_info_3 = IDXPersonalInfo()
+ idx_personal_info_3.account_address = _account_address_3
+ idx_personal_info_3.issuer_address = _issuer_address
+ idx_personal_info_3.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": "birth_test3",
+ # PersonalInfo is partially registered.
+ }
+ db.add(idx_personal_info_3)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(_token_address),
+ headers={"issuer-address": _issuer_address},
+ params={"sort_order": 1, "sort_item": "balance_and_pending_transfer"},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 3, "total": 3, "offset": None, "limit": None},
+ "holders": [
+ {
+ "account_address": _account_address_3,
+ "personal_information": {
+ "key_manager": "key_manager_test1",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": "birth_test3",
+ "is_corporate": None,
+ "tax_category": None,
+ },
+ "balance": 99,
+ "exchange_balance": 99,
+ "exchange_commitment": 99,
+ "pending_transfer": 99,
+ "locked": 30,
+ "modified": "2023-10-24T05:00:00",
+ },
+ {
+ "account_address": _account_address_2,
+ "personal_information": {
+ "key_manager": None,
+ "name": None,
+ "postal_code": None,
+ "address": None,
+ "email": None,
+ "birth": None,
+ "is_corporate": None,
+ "tax_category": None,
+ },
+ "balance": 20,
+ "exchange_balance": 21,
+ "exchange_commitment": 22,
+ "pending_transfer": 10,
+ "locked": 20,
+ "modified": "2023-10-24T02:20:00",
+ },
+ {
+ "account_address": _account_address_1,
+ "personal_information": {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "balance": 10,
+ "exchange_balance": 11,
+ "exchange_commitment": 12,
+ "pending_transfer": 5,
+ "locked": 10,
+ "modified": "2023-10-24T01:10:00",
+ },
+ ],
+ }
+
+ #
+ # Sort Item: holder_name
+ def test_normal_5_7(self, client, db):
+ user = config_eth_account("user1")
+ _issuer_address = user["address"]
+ _token_address = "0x82b1c9374aB625380bd498a3d9dF4033B8A0E3Bb"
+ _account_address_1 = "0xb75c7545b9230FEe99b7af370D38eBd3DAD929f7"
+ _account_address_2 = "0x3F198534Bbe3B2a197d3B317d41392F348EAC707"
+ _account_address_3 = "0x8277D905F37F8a9717F5718d0daC21495dFE74bf"
_account_address_4 = "0x917eFFaC072dcda308e2337636f562D0A96F42eA"
account = Account()
@@ -4350,7 +5237,7 @@ def test_normal_5_6(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -4594,9 +5481,9 @@ def test_normal_5_6(self, client, db):
],
}
- #
+ #
# Sort Item: key_manager
- def test_normal_5_7(self, client, db):
+ def test_normal_5_8(self, client, db):
user = config_eth_account("user1")
_issuer_address = user["address"]
_token_address = "0x82b1c9374aB625380bd498a3d9dF4033B8A0E3Bb"
@@ -4615,7 +5502,7 @@ def test_normal_5_7(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -4879,7 +5766,7 @@ def test_normal_6_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -5090,7 +5977,7 @@ def test_normal_6_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: account_address_1
@@ -5331,7 +6218,7 @@ def test_error_4(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data
diff --git a/tests/test_app_routers_share_tokens_{token_address}_holders_count_GET.py b/tests/app/test_share_tokens_{token_address}_holders_count_GET.py
similarity index 98%
rename from tests/test_app_routers_share_tokens_{token_address}_holders_count_GET.py
rename to tests/app/test_share_tokens_{token_address}_holders_count_GET.py
index caf651be..c92a00b5 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_holders_count_GET.py
+++ b/tests/app/test_share_tokens_{token_address}_holders_count_GET.py
@@ -55,7 +55,7 @@ def test_normal_1_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -90,7 +90,7 @@ def test_normal_1_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
idx_position_1 = IDXPosition()
@@ -134,7 +134,7 @@ def test_normal_1_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
idx_position_1 = IDXPosition()
@@ -196,7 +196,7 @@ def test_normal_1_4(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
idx_position_1 = IDXPosition()
@@ -250,7 +250,7 @@ def test_normal_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
idx_position_1 = IDXPosition()
@@ -417,7 +417,7 @@ def test_error_4(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_share_tokens_{token_address}_holders_{account_address}_GET.py b/tests/app/test_share_tokens_{token_address}_holders_{account_address}_GET.py
similarity index 98%
rename from tests/test_app_routers_share_tokens_{token_address}_holders_{account_address}_GET.py
rename to tests/app/test_share_tokens_{token_address}_holders_{account_address}_GET.py
index 52c153f8..d65a4e42 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_holders_{account_address}_GET.py
+++ b/tests/app/test_share_tokens_{token_address}_holders_{account_address}_GET.py
@@ -60,7 +60,7 @@ def test_normal_1_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: Personal Info
@@ -130,7 +130,7 @@ def test_normal_1_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: Position
@@ -211,7 +211,7 @@ def test_normal_1_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# prepare data: Position
@@ -311,7 +311,7 @@ def test_normal_2_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
idx_position_1 = IDXPosition()
@@ -373,7 +373,7 @@ def test_normal_2_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
idx_position_1 = IDXPosition()
@@ -529,7 +529,7 @@ def test_error_4(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_share_tokens_{token_address}_personal_info_POST.py b/tests/app/test_share_tokens_{token_address}_personal_info_POST.py
similarity index 99%
rename from tests/test_app_routers_share_tokens_{token_address}_personal_info_POST.py
rename to tests/app/test_share_tokens_{token_address}_personal_info_POST.py
index 19350ac6..b4e55b75 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_personal_info_POST.py
+++ b/tests/app/test_share_tokens_{token_address}_personal_info_POST.py
@@ -59,7 +59,7 @@ def test_normal_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -140,7 +140,7 @@ def test_normal_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -227,7 +227,7 @@ def test_normal_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -680,7 +680,7 @@ def test_error_4(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -738,7 +738,7 @@ def test_error_5(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_share_tokens_{token_address}_personal_info_batch_GET.py b/tests/app/test_share_tokens_{token_address}_personal_info_batch_GET.py
similarity index 97%
rename from tests/test_app_routers_share_tokens_{token_address}_personal_info_batch_GET.py
rename to tests/app/test_share_tokens_{token_address}_personal_info_batch_GET.py
index ffdb0222..2c21df4b 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_personal_info_batch_GET.py
+++ b/tests/app/test_share_tokens_{token_address}_personal_info_batch_GET.py
@@ -61,7 +61,7 @@ def test_normal_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -94,7 +94,7 @@ def test_normal_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# Prepare data : BatchRegisterPersonalInfoUpload
@@ -153,7 +153,7 @@ def test_normal_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# Prepare data : BatchRegisterPersonalInfoUpload
@@ -208,7 +208,7 @@ def test_normal_4(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# Prepare data : BatchRegisterPersonalInfoUpload
@@ -263,7 +263,7 @@ def test_normal_5(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# Prepare data : BatchRegisterPersonalInfoUpload
@@ -327,7 +327,7 @@ def test_error_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -370,7 +370,7 @@ def test_error_2(self, client, db):
token.issuer_address = _issuer_address_2
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# Prepare data : BatchRegisterPersonalInfoUpload
diff --git a/tests/test_app_routers_share_tokens_{token_address}_personal_info_batch_POST.py b/tests/app/test_share_tokens_{token_address}_personal_info_batch_POST.py
similarity index 99%
rename from tests/test_app_routers_share_tokens_{token_address}_personal_info_batch_POST.py
rename to tests/app/test_share_tokens_{token_address}_personal_info_batch_POST.py
index 6fbe7814..a1398fd8 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_personal_info_batch_POST.py
+++ b/tests/app/test_share_tokens_{token_address}_personal_info_batch_POST.py
@@ -70,7 +70,7 @@ def test_normal_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -147,7 +147,7 @@ def test_normal_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -668,7 +668,7 @@ def test_error_4_1(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -730,7 +730,7 @@ def test_error_4_2(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 1
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_share_tokens_{token_address}_personal_info_batch_{batch_id}_GET.py b/tests/app/test_share_tokens_{token_address}_personal_info_batch_{batch_id}_GET.py
similarity index 99%
rename from tests/test_app_routers_share_tokens_{token_address}_personal_info_batch_{batch_id}_GET.py
rename to tests/app/test_share_tokens_{token_address}_personal_info_batch_{batch_id}_GET.py
index 17b55235..2c49b538 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_personal_info_batch_{batch_id}_GET.py
+++ b/tests/app/test_share_tokens_{token_address}_personal_info_batch_{batch_id}_GET.py
@@ -94,7 +94,7 @@ def test_normal_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
# Prepare data : BatchRegisterPersonalInfoUpload
diff --git a/tests/test_app_routers_share_tokens_{token_address}_redeem_GET.py b/tests/app/test_share_tokens_{token_address}_redeem_GET.py
similarity index 98%
rename from tests/test_app_routers_share_tokens_{token_address}_redeem_GET.py
rename to tests/app/test_share_tokens_{token_address}_redeem_GET.py
index 6fe6f33b..e85f8fb1 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_redeem_GET.py
+++ b/tests/app/test_share_tokens_{token_address}_redeem_GET.py
@@ -74,7 +74,7 @@ def test_normal_1(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXIssueRedeem
@@ -110,7 +110,7 @@ def test_normal_2(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXIssueRedeem
@@ -191,7 +191,7 @@ def test_normal_3(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXIssueRedeem
@@ -278,7 +278,7 @@ def test_normal_4(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXIssueRedeem
@@ -365,7 +365,7 @@ def test_error_2(self, client, db):
_token.token_address = self.test_token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -425,7 +425,7 @@ def test_error_4_1(self, client, db):
"detail": [
{
"ctx": {"expected": "0 or 1"},
- "input": -1,
+ "input": "-1",
"loc": ["query", "sort_order"],
"msg": "Input should be 0 or 1",
"type": "enum",
@@ -449,7 +449,7 @@ def test_error_4_2(self, client, db):
"detail": [
{
"ctx": {"expected": "0 or 1"},
- "input": 2,
+ "input": "2",
"loc": ["query", "sort_order"],
"msg": "Input should be 0 or 1",
"type": "enum",
diff --git a/tests/test_app_routers_share_tokens_{token_address}_redeem_POST.py b/tests/app/test_share_tokens_{token_address}_redeem_POST.py
similarity index 98%
rename from tests/test_app_routers_share_tokens_{token_address}_redeem_POST.py
rename to tests/app/test_share_tokens_{token_address}_redeem_POST.py
index 810b41d4..7edbd68c 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_redeem_POST.py
+++ b/tests/app/test_share_tokens_{token_address}_redeem_POST.py
@@ -58,7 +58,7 @@ def test_normal_1(self, IbetShareContract_mock, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -113,7 +113,7 @@ def test_normal_2(self, IbetShareContract_mock, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -283,7 +283,7 @@ def test_error_5(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -326,7 +326,7 @@ def test_error_6(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -440,7 +440,7 @@ def test_error_9(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -488,7 +488,7 @@ def test_error_10(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_share_tokens_{token_address}_redeem_batch_GET.py b/tests/app/test_share_tokens_{token_address}_redeem_batch_GET.py
similarity index 98%
rename from tests/test_app_routers_share_tokens_{token_address}_redeem_batch_GET.py
rename to tests/app/test_share_tokens_{token_address}_redeem_batch_GET.py
index 22806df0..ceed3d88 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_redeem_batch_GET.py
+++ b/tests/app/test_share_tokens_{token_address}_redeem_batch_GET.py
@@ -52,7 +52,7 @@ def test_normal_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -80,7 +80,7 @@ def test_normal_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
redeem_upload1 = BatchIssueRedeemUpload()
@@ -127,7 +127,7 @@ def test_normal_3_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
redeem_upload1 = BatchIssueRedeemUpload()
@@ -234,7 +234,7 @@ def test_normal_3_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
redeem_upload1 = BatchIssueRedeemUpload()
@@ -328,7 +328,7 @@ def test_normal_3_3(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
redeem_upload1 = BatchIssueRedeemUpload()
@@ -428,7 +428,7 @@ def test_normal_4(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
redeem_upload1 = BatchIssueRedeemUpload()
@@ -520,7 +520,7 @@ def test_normal_5(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
additional_issue_upload1 = BatchIssueRedeemUpload()
@@ -643,7 +643,7 @@ def test_error_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_share_tokens_{token_address}_redeem_batch_POST.py b/tests/app/test_share_tokens_{token_address}_redeem_batch_POST.py
similarity index 97%
rename from tests/test_app_routers_share_tokens_{token_address}_redeem_batch_POST.py
rename to tests/app/test_share_tokens_{token_address}_redeem_batch_POST.py
index c2a8a2ba..a7f56bb1 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_redeem_batch_POST.py
+++ b/tests/app/test_share_tokens_{token_address}_redeem_batch_POST.py
@@ -66,7 +66,7 @@ def test_normal_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -131,7 +131,7 @@ def test_normal_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -206,7 +206,7 @@ def test_error_1_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -258,7 +258,7 @@ def test_error_1_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -313,7 +313,7 @@ def test_error_1_3_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -368,7 +368,7 @@ def test_error_1_3_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -423,7 +423,7 @@ def test_error_1_4(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -472,7 +472,7 @@ def test_error_1_5(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -521,7 +521,7 @@ def test_error_1_6(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -568,7 +568,7 @@ def test_error_1_7_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -615,7 +615,7 @@ def test_error_1_7_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -703,7 +703,7 @@ def test_error_1_8_2(self, client, db):
token.token_address = token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_share_tokens_{token_address}_redeem_batch_{batch_id}_GET.py b/tests/app/test_share_tokens_{token_address}_redeem_batch_{batch_id}_GET.py
similarity index 98%
rename from tests/test_app_routers_share_tokens_{token_address}_redeem_batch_{batch_id}_GET.py
rename to tests/app/test_share_tokens_{token_address}_redeem_batch_{batch_id}_GET.py
index 3a77f631..f31eeeb4 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_redeem_batch_{batch_id}_GET.py
+++ b/tests/app/test_share_tokens_{token_address}_redeem_batch_{batch_id}_GET.py
@@ -71,7 +71,7 @@ def test_normal_1_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = test_token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
batch_upload = BatchIssueRedeemUpload()
@@ -158,7 +158,7 @@ def test_normal_1_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = test_token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
batch_upload = BatchIssueRedeemUpload()
@@ -245,7 +245,7 @@ def test_normal_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = test_token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
batch_upload = BatchIssueRedeemUpload()
@@ -358,7 +358,7 @@ def test_error_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = test_token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
batch_upload = BatchIssueRedeemUpload()
diff --git a/tests/test_app_routers_share_tokens_{token_address}_scheduled_events_GET.py b/tests/app/test_share_tokens_{token_address}_scheduled_events_GET.py
similarity index 93%
rename from tests/test_app_routers_share_tokens_{token_address}_scheduled_events_GET.py
rename to tests/app/test_share_tokens_{token_address}_scheduled_events_GET.py
index ac156b14..86b5b6a3 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_scheduled_events_GET.py
+++ b/tests/app/test_share_tokens_{token_address}_scheduled_events_GET.py
@@ -18,9 +18,9 @@
"""
import uuid
-from datetime import datetime, timedelta
+from datetime import UTC, datetime, timedelta
-from pytz import timezone
+import pytz
from app.model.db import ScheduledEvents, ScheduledEventType, TokenType
from config import TZ
@@ -30,7 +30,7 @@
class TestAppRoutersShareTokensTokenAddressScheduledEventsGET:
# target API endpoint
base_url = "/share/tokens/{}/scheduled_events"
- local_tz = timezone(TZ)
+ local_tz = pytz.timezone(TZ)
###########################################################################
# Normal Case
@@ -45,9 +45,9 @@ def test_normal_1(self, client, db):
_token_address = "token_address_test"
# prepare data
- datetime_now_utc = datetime.utcnow()
+ datetime_now_utc = datetime.now(UTC).replace(tzinfo=None)
datetime_now_str = (
- timezone("UTC")
+ pytz.timezone("UTC")
.localize(datetime_now_utc)
.astimezone(self.local_tz)
.isoformat()
@@ -117,9 +117,9 @@ def test_normal_2(self, client, db):
# prepare data
datetime_list = []
- datetime_utc = datetime.utcnow() + timedelta(hours=1)
+ datetime_utc = datetime.now(UTC).replace(tzinfo=None) + timedelta(hours=1)
datetime_list.append(datetime_utc)
- datetime_utc = datetime.utcnow()
+ datetime_utc = datetime.now(UTC).replace(tzinfo=None)
datetime_list.append(datetime_utc)
uuid_list = [str(uuid.uuid4()), str(uuid.uuid4())]
@@ -167,14 +167,14 @@ def test_normal_2(self, client, db):
"scheduled_event_id": uuid_list[0],
"token_address": _token_address,
"token_type": TokenType.IBET_SHARE.value,
- "scheduled_datetime": timezone("UTC")
+ "scheduled_datetime": pytz.timezone("UTC")
.localize(datetime_list[0])
.astimezone(self.local_tz)
.isoformat(),
"event_type": ScheduledEventType.UPDATE.value,
"status": 0,
"data": update_data,
- "created": timezone("UTC")
+ "created": pytz.timezone("UTC")
.localize(datetime_list[0])
.astimezone(self.local_tz)
.isoformat(),
@@ -183,14 +183,14 @@ def test_normal_2(self, client, db):
"scheduled_event_id": uuid_list[1],
"token_address": _token_address,
"token_type": TokenType.IBET_SHARE.value,
- "scheduled_datetime": timezone("UTC")
+ "scheduled_datetime": pytz.timezone("UTC")
.localize(datetime_list[1])
.astimezone(self.local_tz)
.isoformat(),
"event_type": ScheduledEventType.UPDATE.value,
"status": 0,
"data": update_data,
- "created": timezone("UTC")
+ "created": pytz.timezone("UTC")
.localize(datetime_list[1])
.astimezone(self.local_tz)
.isoformat(),
diff --git a/tests/test_app_routers_share_tokens_{token_address}_scheduled_events_POST.py b/tests/app/test_share_tokens_{token_address}_scheduled_events_POST.py
similarity index 87%
rename from tests/test_app_routers_share_tokens_{token_address}_scheduled_events_POST.py
rename to tests/app/test_share_tokens_{token_address}_scheduled_events_POST.py
index c3e33e10..75594707 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_scheduled_events_POST.py
+++ b/tests/app/test_share_tokens_{token_address}_scheduled_events_POST.py
@@ -17,7 +17,7 @@
SPDX-License-Identifier: Apache-2.0
"""
-from datetime import datetime, timezone
+from datetime import UTC, datetime
from pytz import timezone as tz
from sqlalchemy import and_, select
@@ -63,13 +63,13 @@ def test_normal_1(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
# test data
- datetime_now_utc = datetime.now(timezone.utc) # utc
+ datetime_now_utc = datetime.now(UTC) # utc
datetime_now_str = datetime_now_utc.isoformat()
update_data = {
"cancellation_date": "20221231",
@@ -78,6 +78,7 @@ def test_normal_1(self, client, db):
"dividend_payment_date": "20211231",
"tradable_exchange_contract_address": "0xe883A6f441Ad5682d37DF31d34fc012bcB07A740",
"personal_info_contract_address": "0xa4CEe3b909751204AA151860ebBE8E7A851c2A1a",
+ "require_personal_info_registered": False,
"transferable": False,
"status": False,
"is_offering": False,
@@ -146,7 +147,7 @@ def test_normal_2(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -161,6 +162,7 @@ def test_normal_2(self, client, db):
"dividend_payment_date": "20211231",
"tradable_exchange_contract_address": "0xe883A6f441Ad5682d37DF31d34fc012bcB07A740",
"personal_info_contract_address": "0xa4CEe3b909751204AA151860ebBE8E7A851c2A1a",
+ "require_personal_info_registered": False,
"transferable": False,
"status": False,
"is_offering": False,
@@ -198,7 +200,7 @@ def test_normal_2(self, client, db):
assert resp.json() == {"scheduled_event_id": _scheduled_event.event_id}
assert _scheduled_event.token_type == TokenType.IBET_SHARE.value
assert _scheduled_event.scheduled_datetime == datetime_now_jst.astimezone(
- timezone.utc
+ UTC
).replace(tzinfo=None)
assert _scheduled_event.event_type == ScheduledEventType.UPDATE.value
assert _scheduled_event.status == 0
@@ -216,7 +218,7 @@ def test_error_1_1(self, client, db):
_token_address = "token_address_test"
# test data
- datetime_now_utc = datetime.now(timezone.utc)
+ datetime_now_utc = datetime.now(UTC)
datetime_now_str = datetime_now_utc.isoformat()
update_data = {}
@@ -261,7 +263,7 @@ def test_error_1_2(self, client, db):
_token_address = "token_address_test"
# test data
- datetime_now_utc = datetime.now(timezone.utc)
+ datetime_now_utc = datetime.now(UTC)
datetime_now_str = datetime_now_utc.isoformat()
update_data = {"is_canceled": False}
@@ -302,7 +304,7 @@ def test_error_2(self, client, db):
_token_address = "token_address_test"
# test data
- datetime_now_utc = datetime.now(timezone.utc)
+ datetime_now_utc = datetime.now(UTC)
datetime_now_str = datetime_now_utc.isoformat()
update_data = {}
@@ -348,13 +350,13 @@ def test_error_3(self, client, db):
token.issuer_address = _issuer_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
# test data
- datetime_now_utc = datetime.now(timezone.utc)
+ datetime_now_utc = datetime.now(UTC)
datetime_now_str = datetime_now_utc.isoformat()
update_data = {}
@@ -397,7 +399,7 @@ def test_error_4(self, client, db):
db.commit()
# test data
- datetime_now_utc = datetime.now(timezone.utc)
+ datetime_now_utc = datetime.now(UTC)
datetime_now_str = datetime_now_utc.isoformat()
update_data = {}
@@ -495,13 +497,13 @@ def test_error_6(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
# test data
- datetime_now_utc = datetime.now(timezone.utc)
+ datetime_now_utc = datetime.now(UTC)
datetime_now_str = datetime_now_utc.isoformat()
update_data = {}
@@ -526,3 +528,59 @@ def test_error_6(self, client, db):
"meta": {"code": 1, "title": "InvalidParameterError"},
"detail": "this token is temporarily unavailable",
}
+
+ #
+ # OperationNotSupportedVersionError: v24.6
+ def test_error_7(self, client, db):
+ test_account = config_eth_account("user1")
+ _issuer_address = test_account["address"]
+ _keyfile = test_account["keyfile_json"]
+ _token_address = "token_address_test"
+
+ # prepare data
+ account = Account()
+ account.issuer_address = _issuer_address
+ account.keyfile = _keyfile
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ token = Token()
+ token.type = TokenType.IBET_SHARE.value
+ token.tx_hash = ""
+ token.issuer_address = _issuer_address
+ token.token_address = _token_address
+ token.abi = ""
+ token.token_status = 1
+ token.version = TokenVersion.V_22_12
+ db.add(token)
+
+ db.commit()
+
+ # test data
+ datetime_now_utc = datetime.now(UTC)
+ datetime_now_str = datetime_now_utc.isoformat()
+ update_data = {
+ "require_personal_info_registered": False,
+ }
+
+ # request target API
+ req_param = {
+ "scheduled_datetime": datetime_now_str,
+ "event_type": "Update",
+ "data": update_data,
+ }
+ resp = client.post(
+ self.base_url.format(_token_address),
+ json=req_param,
+ headers={
+ "issuer-address": _issuer_address,
+ "eoa-password": E2EEUtils.encrypt("password"),
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 400
+ assert resp.json() == {
+ "meta": {"code": 6, "title": "OperationNotSupportedVersionError"},
+ "detail": "the operation is not supported in 22_12",
+ }
diff --git a/tests/test_app_routers_share_tokens_{token_address}_scheduled_events_{scheduled_event_id}_DELETE.py b/tests/app/test_share_tokens_{token_address}_scheduled_events_{scheduled_event_id}_DELETE.py
similarity index 97%
rename from tests/test_app_routers_share_tokens_{token_address}_scheduled_events_{scheduled_event_id}_DELETE.py
rename to tests/app/test_share_tokens_{token_address}_scheduled_events_{scheduled_event_id}_DELETE.py
index a331be58..f2bd9265 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_scheduled_events_{scheduled_event_id}_DELETE.py
+++ b/tests/app/test_share_tokens_{token_address}_scheduled_events_{scheduled_event_id}_DELETE.py
@@ -18,9 +18,9 @@
"""
import uuid
-from datetime import datetime
+from datetime import UTC, datetime
-from pytz import timezone
+import pytz
from sqlalchemy import select
from app.model.db import Account, ScheduledEvents, ScheduledEventType, TokenType
@@ -32,7 +32,7 @@
class TestAppRoutersShareTokensTokenAddressScheduledEventsScheduledEventIdDELETE:
# target API endpoint
base_url = "/share/tokens/{}/scheduled_events/{}"
- local_tz = timezone(TZ)
+ local_tz = pytz.timezone(TZ)
###########################################################################
# Normal Case
@@ -52,9 +52,9 @@ def test_normal_1(self, client, db):
account.eoa_password = E2EEUtils.encrypt("password")
db.add(account)
- datetime_now_utc = datetime.utcnow()
+ datetime_now_utc = datetime.now(UTC).replace(tzinfo=None)
datetime_now_str = (
- timezone("UTC")
+ pytz.timezone("UTC")
.localize(datetime_now_utc)
.astimezone(self.local_tz)
.isoformat()
diff --git a/tests/test_app_routers_share_tokens_{token_address}_scheduled_events_{scheduled_event_id}_GET.py b/tests/app/test_share_tokens_{token_address}_scheduled_events_{scheduled_event_id}_GET.py
similarity index 95%
rename from tests/test_app_routers_share_tokens_{token_address}_scheduled_events_{scheduled_event_id}_GET.py
rename to tests/app/test_share_tokens_{token_address}_scheduled_events_{scheduled_event_id}_GET.py
index 12c9e1a3..ebfe10d2 100644
--- a/tests/test_app_routers_share_tokens_{token_address}_scheduled_events_{scheduled_event_id}_GET.py
+++ b/tests/app/test_share_tokens_{token_address}_scheduled_events_{scheduled_event_id}_GET.py
@@ -18,9 +18,9 @@
"""
import uuid
-from datetime import datetime
+from datetime import UTC, datetime
-from pytz import timezone
+import pytz
from app.model.db import ScheduledEvents, ScheduledEventType, TokenType
from config import TZ
@@ -30,7 +30,7 @@
class TestAppRoutersShareTokensTokenAddressScheduledEventsScheduledEventIdGET:
# target API endpoint
base_url = "/share/tokens/{}/scheduled_events/{}"
- local_tz = timezone(TZ)
+ local_tz = pytz.timezone(TZ)
###########################################################################
# Normal Case
@@ -45,9 +45,9 @@ def test_normal_1(self, client, db):
_token_address = "token_address_test"
# prepare data
- datetime_now_utc = datetime.utcnow()
+ datetime_now_utc = datetime.now(UTC).replace(tzinfo=None)
datetime_now_str = (
- timezone("UTC")
+ pytz.timezone("UTC")
.localize(datetime_now_utc)
.astimezone(self.local_tz)
.isoformat()
@@ -113,9 +113,9 @@ def test_normal_2(self, client, db):
_token_address = "token_address_test"
# prepare data
- datetime_now_utc = datetime.utcnow()
+ datetime_now_utc = datetime.now(UTC).replace(tzinfo=None)
datetime_now_str = (
- timezone("UTC")
+ pytz.timezone("UTC")
.localize(datetime_now_utc)
.astimezone(self.local_tz)
.isoformat()
diff --git a/tests/test_app_routers_share_transfer_approvals_GET.py b/tests/app/test_share_transfer_approvals_GET.py
similarity index 98%
rename from tests/test_app_routers_share_transfer_approvals_GET.py
rename to tests/app/test_share_transfer_approvals_GET.py
index 266d8756..a3728b3f 100644
--- a/tests/test_app_routers_share_transfer_approvals_GET.py
+++ b/tests/app/test_share_transfer_approvals_GET.py
@@ -100,7 +100,7 @@ def test_normal_1(self, client, db):
_token.token_address = self.test_token_address_1
_token.abi = {}
_token.token_status = 2
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Token(bond)
@@ -110,7 +110,7 @@ def test_normal_1(self, client, db):
_token.issuer_address = self.test_issuer_address_1
_token.token_address = self.test_token_address_2
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval(failed token)
@@ -201,7 +201,7 @@ def test_normal_2(self, client, db):
_token.issuer_address = self.test_issuer_address_1
_token.token_address = self.test_token_address_1
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval(ApplyFor(unapproved))
@@ -386,7 +386,7 @@ def test_normal_3_1(self, client, db):
_token.issuer_address = self.test_issuer_address_1
_token.token_address = self.test_token_address_1
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Token(issuer-1)
@@ -396,7 +396,7 @@ def test_normal_3_1(self, client, db):
_token.issuer_address = self.test_issuer_address_1
_token.token_address = self.test_token_address_2
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Token(issuer-2)
@@ -406,7 +406,7 @@ def test_normal_3_1(self, client, db):
_token.issuer_address = self.test_issuer_address_2
_token.token_address = self.test_token_address_3
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval(issuer-1 token-1)
@@ -571,7 +571,7 @@ def test_normal_3_2(self, client, db):
_token.issuer_address = self.test_issuer_address_1
_token.token_address = self.test_token_address_1
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Token(issuer-1)
@@ -581,7 +581,7 @@ def test_normal_3_2(self, client, db):
_token.issuer_address = self.test_issuer_address_1
_token.token_address = self.test_token_address_2
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Token(issuer-2)
@@ -591,7 +591,7 @@ def test_normal_3_2(self, client, db):
_token.issuer_address = self.test_issuer_address_2
_token.token_address = self.test_token_address_3
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval(issuer-1 token-1)
@@ -763,7 +763,7 @@ def test_normal_4(self, client, db):
_token.issuer_address = self.test_issuer_address_1
_token.token_address = self.test_token_address_1
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Token(issuer-1)
@@ -773,7 +773,7 @@ def test_normal_4(self, client, db):
_token.issuer_address = self.test_issuer_address_1
_token.token_address = self.test_token_address_2
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Token(issuer-1)
@@ -783,7 +783,7 @@ def test_normal_4(self, client, db):
_token.issuer_address = self.test_issuer_address_1
_token.token_address = self.test_token_address_3
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: Token(issuer-1)
@@ -793,7 +793,7 @@ def test_normal_4(self, client, db):
_token.issuer_address = self.test_issuer_address_1
_token.token_address = self.test_token_address_4
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval(issuer-1 token-1)
diff --git a/tests/test_app_routers_share_transfer_approvals_{token_address}_GET.py b/tests/app/test_share_transfer_approvals_{token_address}_GET.py
similarity index 99%
rename from tests/test_app_routers_share_transfer_approvals_{token_address}_GET.py
rename to tests/app/test_share_transfer_approvals_{token_address}_GET.py
index e3eec139..27a41441 100644
--- a/tests/test_app_routers_share_transfer_approvals_{token_address}_GET.py
+++ b/tests/app/test_share_transfer_approvals_{token_address}_GET.py
@@ -110,7 +110,7 @@ def test_normal_1_1(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -136,7 +136,7 @@ def test_normal_1_2(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -330,7 +330,7 @@ def test_normal_2(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -450,7 +450,7 @@ def test_normal_3(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -654,7 +654,7 @@ def test_normal_4_1(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -767,7 +767,7 @@ def test_normal_4_2(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -881,7 +881,7 @@ def test_normal_4_3_1(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -1027,7 +1027,7 @@ def test_normal_4_3_2(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -1173,7 +1173,7 @@ def test_normal_4_3_3(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval
@@ -1407,7 +1407,7 @@ def test_normal_4_3_4(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -1627,7 +1627,7 @@ def test_normal_4_3_5(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -1879,7 +1879,7 @@ def test_normal_5_1(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -2079,7 +2079,7 @@ def test_normal_5_2(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -2319,7 +2319,7 @@ def test_normal_5_3(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -2559,7 +2559,7 @@ def test_normal_5_4(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -2764,7 +2764,7 @@ def test_normal_5_5(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -2967,7 +2967,7 @@ def test_normal_5_6(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -3206,7 +3206,7 @@ def test_normal_5_7(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -3452,7 +3452,7 @@ def test_normal_5_8(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -3694,7 +3694,7 @@ def test_normal_5_9(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -4132,25 +4132,23 @@ def test_error_1_1(self, client, db):
"meta": {"code": 1, "title": "RequestValidationError"},
"detail": [
{
- "input": "a",
+ "type": "enum",
"loc": ["query", "status", 0],
- "msg": "Input should be a valid integer, unable to parse string "
- "as an integer",
- "type": "int_parsing",
+ "msg": "Input should be 0, 1, 2 or 3",
+ "input": "a",
+ "ctx": {"expected": "0, 1, 2 or 3"},
},
{
- "input": "c",
- "loc": ["query", "offset"],
- "msg": "Input should be a valid integer, unable to parse string "
- "as an integer",
"type": "int_parsing",
+ "loc": ["query", "offset"],
+ "msg": "Input should be a valid integer, unable to parse string as an integer",
+ "input": "c",
},
{
- "input": "d",
- "loc": ["query", "limit"],
- "msg": "Input should be a valid integer, unable to parse string "
- "as an integer",
"type": "int_parsing",
+ "loc": ["query", "limit"],
+ "msg": "Input should be a valid integer, unable to parse string as an integer",
+ "input": "d",
},
],
}
@@ -4175,7 +4173,7 @@ def test_error_1_2(self, client, db):
"detail": [
{
"ctx": {"expected": "0, 1, 2 or 3"},
- "input": -1,
+ "input": "-1",
"loc": ["query", "status", 0],
"msg": "Input should be 0, 1, 2 or 3",
"type": "enum",
@@ -4203,7 +4201,7 @@ def test_error_1_3(self, client, db):
"detail": [
{
"ctx": {"expected": "0, 1, 2 or 3"},
- "input": 4,
+ "input": "4",
"loc": ["query", "status", 0],
"msg": "Input should be 0, 1, 2 or 3",
"type": "enum",
@@ -4237,7 +4235,7 @@ def test_error_2(self, client, db):
_token.token_address = self.test_token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
diff --git a/tests/test_app_routers_share_transfer_approvals_{token_address}_{id}_GET.py b/tests/app/test_share_transfer_approvals_{token_address}_{id}_GET.py
similarity index 98%
rename from tests/test_app_routers_share_transfer_approvals_{token_address}_{id}_GET.py
rename to tests/app/test_share_transfer_approvals_{token_address}_{id}_GET.py
index 96601a41..76d249cd 100644
--- a/tests/test_app_routers_share_transfer_approvals_{token_address}_{id}_GET.py
+++ b/tests/app/test_share_transfer_approvals_{token_address}_{id}_GET.py
@@ -96,7 +96,7 @@ def test_normal_1_1(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -209,7 +209,7 @@ def test_normal_1_2(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval
@@ -274,7 +274,7 @@ def test_normal_2_1(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval
@@ -384,7 +384,7 @@ def test_normal_2_2(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval
@@ -496,7 +496,7 @@ def test_normal_3(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -610,7 +610,7 @@ def test_normal_4_1(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval
@@ -722,7 +722,7 @@ def test_normal_4_2(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXTransferApproval
@@ -835,7 +835,7 @@ def test_normal_4_3(self, client, db):
_token.issuer_address = self.test_issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
# prepare data: IDXPersonalInfo
@@ -982,7 +982,7 @@ def test_error_2(self, client, db):
_token.token_address = self.test_token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -1010,7 +1010,7 @@ def test_error_3(self, client, db):
_token.token_address = self.test_token_address
_token.abi = {}
_token.token_status = 1
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
diff --git a/tests/test_app_routers_share_transfer_approvals_{token_address}_{id}_POST.py b/tests/app/test_share_transfer_approvals_{token_address}_{id}_POST.py
similarity index 97%
rename from tests/test_app_routers_share_transfer_approvals_{token_address}_{id}_POST.py
rename to tests/app/test_share_transfer_approvals_{token_address}_{id}_POST.py
index b15f52a7..1c5d9cd7 100644
--- a/tests/test_app_routers_share_transfer_approvals_{token_address}_{id}_POST.py
+++ b/tests/app/test_share_transfer_approvals_{token_address}_{id}_POST.py
@@ -18,12 +18,11 @@
"""
import hashlib
-from datetime import datetime
+from datetime import UTC, datetime
from unittest import mock
from unittest.mock import ANY, MagicMock
import pytest
-from pytz import timezone
from sqlalchemy import select
import config
@@ -49,8 +48,6 @@
from app.utils.e2ee_utils import E2EEUtils
from tests.account_config import config_eth_account
-local_tz = timezone(config.TZ)
-
class TestAppRoutersShareTransferApprovalsTokenAddressIdPOST:
# target API endpoint
@@ -93,7 +90,7 @@ def test_normal_1_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -168,7 +165,10 @@ def test_normal_1_1(self, client, db):
assert resp.status_code == 200
assert resp.json() is None
- _expected = {"application_id": 100, "data": str(datetime.utcnow().timestamp())}
+ _expected = {
+ "application_id": 100,
+ "data": str(datetime.now(UTC).replace(tzinfo=None).timestamp()),
+ }
mock_transfer.assert_called_once_with(
data=ApproveTransferParams(**_expected),
@@ -227,7 +227,7 @@ def test_normal_1_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -303,7 +303,10 @@ def test_normal_1_2(self, client, db):
assert resp.status_code == 200
assert resp.json() is None
- _expected = {"escrow_id": 100, "data": str(datetime.utcnow().timestamp())}
+ _expected = {
+ "escrow_id": 100,
+ "data": str(datetime.now(UTC).replace(tzinfo=None).timestamp()),
+ }
mock_transfer.assert_called_once_with(
data=EscrowApproveTransferParams(**_expected),
@@ -362,7 +365,7 @@ def test_normal_2_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -437,7 +440,10 @@ def test_normal_2_1(self, client, db):
assert resp.status_code == 200
assert resp.json() is None
- _expected = {"application_id": 100, "data": str(datetime.utcnow().timestamp())}
+ _expected = {
+ "application_id": 100,
+ "data": str(datetime.now(UTC).replace(tzinfo=None).timestamp()),
+ }
mock_transfer.assert_called_once_with(
data=CancelTransferParams(**_expected),
@@ -501,7 +507,7 @@ def test_normal_3(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -576,7 +582,10 @@ def test_normal_3(self, client, db):
assert resp.status_code == 200
assert resp.json() is None
- _expected = {"application_id": 100, "data": str(datetime.utcnow().timestamp())}
+ _expected = {
+ "application_id": 100,
+ "data": str(datetime.now(UTC).replace(tzinfo=None).timestamp()),
+ }
mock_transfer.assert_called_once_with(
data=ApproveTransferParams(**_expected),
@@ -832,7 +841,7 @@ def test_error_3_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -877,7 +886,7 @@ def test_error_4_1(self, client, db):
_token.token_address = self.test_token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -921,7 +930,7 @@ def test_error_4_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -986,7 +995,7 @@ def test_error_4_3(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1051,7 +1060,7 @@ def test_error_4_4(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1114,7 +1123,7 @@ def test_error_4_5(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1177,7 +1186,7 @@ def test_error_4_6(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1253,7 +1262,7 @@ def test_error_5_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1346,7 +1355,7 @@ def test_error_5_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1456,7 +1465,7 @@ def test_error_5_3(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1550,7 +1559,7 @@ def test_error_5_4(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1655,7 +1664,7 @@ def test_error_6_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1748,7 +1757,7 @@ def test_error_6_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1846,7 +1855,7 @@ def test_error_7_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
@@ -1914,7 +1923,7 @@ def test_error_7_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = self.test_token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
id = 10
diff --git a/tests/test_app_routers_share_transfers_POST.py b/tests/app/test_share_transfers_POST.py
similarity index 99%
rename from tests/test_app_routers_share_transfers_POST.py
rename to tests/app/test_share_transfers_POST.py
index 1f8e5c50..a0de6e71 100644
--- a/tests/test_app_routers_share_transfers_POST.py
+++ b/tests/app/test_share_transfers_POST.py
@@ -65,7 +65,7 @@ def test_normal_1(self, IbetShareContract_mock, client, db):
token.issuer_address = _admin_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -140,7 +140,7 @@ def test_normal_2(self, IbetShareContract_mock, client, db):
token.issuer_address = _admin_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -547,7 +547,7 @@ def test_error_9(self, client, db):
token.token_address = _token_address
token.abi = ""
token.token_status = 0
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -607,7 +607,7 @@ def test_error_10(self, client, db):
token.issuer_address = _admin_address
token.token_address = _token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/app/test_share_transfers_{token_address}_GET.py b/tests/app/test_share_transfers_{token_address}_GET.py
new file mode 100644
index 00000000..7c4fe4b3
--- /dev/null
+++ b/tests/app/test_share_transfers_{token_address}_GET.py
@@ -0,0 +1,1950 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+from datetime import datetime
+
+from pytz import timezone
+
+import config
+from app.model.db import (
+ IDXPersonalInfo,
+ IDXTransfer,
+ IDXTransferSourceEventType,
+ Token,
+ TokenType,
+ TokenVersion,
+)
+
+local_tz = timezone(config.TZ)
+
+
+class TestAppRoutersShareTransfersGET:
+ # target API endpoint
+ base_url = "/share/transfers/{}"
+
+ test_transaction_hash = "test_transaction_hash"
+ test_issuer_address = "test_issuer_address"
+ test_token_address = "test_token_address"
+
+ test_from_address_1 = "test_from_address_1"
+ test_from_address_2 = "test_from_address_2"
+ test_to_address_1 = "test_to_address_1"
+ test_to_address_2 = "test_to_address_2"
+
+ test_block_timestamp = [
+ datetime.strptime("2022/01/02 15:20:30", "%Y/%m/%d %H:%M:%S"), # JST 2022/01/03
+ datetime.strptime("2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"), # JST 2022/01/02
+ datetime.strptime("2022/01/02 00:20:30", "%Y/%m/%d %H:%M:%S"), # JST 2022/01/02
+ ]
+ test_block_timestamp_str = [
+ "2022-01-03T00:20:30+09:00",
+ "2022-01-02T00:20:30+09:00",
+ "2022-01-02T09:20:30+09:00",
+ ]
+
+ ###########################################################################
+ # Normal Case
+ ###########################################################################
+
+ #
+ # default sort
+ def test_normal_1(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_SHARE.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ for i in range(0, 3):
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = i
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[i]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(self.base_url.format(self.test_token_address))
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 3, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 0,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 1,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # offset, limit
+ def test_normal_2(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_SHARE.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXPersonalInfo
+ _personal_info_from = IDXPersonalInfo()
+ _personal_info_from.account_address = self.test_from_address_1
+ _personal_info_from.issuer_address = self.test_issuer_address
+ _personal_info_from._personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "テスト太郎1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ } # latest data
+ db.add(_personal_info_from)
+
+ _personal_info_to = IDXPersonalInfo()
+ _personal_info_to.account_address = self.test_to_address_1
+ _personal_info_to.issuer_address = self.test_issuer_address
+ _personal_info_to._personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "テスト太郎2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ } # latest data
+ db.add(_personal_info_to)
+
+ # prepare data: IDXTransfer
+ for i in range(0, 3):
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = i
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[i]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address) + "?offset=1&limit=1"
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 3, "offset": 1, "limit": 1, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": {
+ "address": "address_test1",
+ "birth": "birth_test1",
+ "email": "email_test1",
+ "is_corporate": False,
+ "key_manager": "key_manager_test1",
+ "name": "テスト太郎1",
+ "postal_code": "postal_code_test1",
+ "tax_category": 10,
+ },
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": {
+ "address": "address_test2",
+ "birth": "birth_test2",
+ "email": "email_test2",
+ "is_corporate": False,
+ "key_manager": "key_manager_test2",
+ "name": "テスト太郎2",
+ "postal_code": "postal_code_test2",
+ "tax_category": 10,
+ },
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: block_timestamp_from
+ def test_normal_3_1(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_SHARE.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 2
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"block_timestamp_from": "2022-01-02T09:20:30"},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 2, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 0,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: block_timestamp_to
+ def test_normal_3_2(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_SHARE.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 2
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"block_timestamp_to": "2022-01-02T09:20:30"},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 2, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 1,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: from_address
+ def test_normal_3_3(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_SHARE.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_2
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_2
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 2
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"from_address": self.test_from_address_1},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 1, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: to_address
+ def test_normal_3_4(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_SHARE.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_2
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_2
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 2
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"to_address": self.test_to_address_1},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 1, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: from_address_name
+ def test_normal_3_5(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_SHARE.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_2
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ # prepare data: IDXPersonalInfo
+ _personal_info_from = IDXPersonalInfo()
+ _personal_info_from.account_address = self.test_from_address_1
+ _personal_info_from.issuer_address = self.test_issuer_address
+ _personal_info_from._personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "テスト太郎1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ } # latest data
+ db.add(_personal_info_from)
+
+ _personal_info_to = IDXPersonalInfo()
+ _personal_info_to.account_address = self.test_from_address_2
+ _personal_info_to.issuer_address = self.test_issuer_address
+ _personal_info_to._personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "テスト太郎2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ } # latest data
+ db.add(_personal_info_to)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"from_address_name": "テスト太郎1"}, # test_from_address_1's name
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 1, "offset": None, "limit": None, "total": 2},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": {
+ "key_manager": "key_manager_test1",
+ "name": "テスト太郎1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 0,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: to_address_name
+ def test_normal_3_6(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_SHARE.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_2
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ # prepare data: IDXPersonalInfo
+ _personal_info_from = IDXPersonalInfo()
+ _personal_info_from.account_address = self.test_to_address_1
+ _personal_info_from.issuer_address = self.test_issuer_address
+ _personal_info_from._personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "テスト太郎1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ } # latest data
+ db.add(_personal_info_from)
+
+ _personal_info_to = IDXPersonalInfo()
+ _personal_info_to.account_address = self.test_to_address_2
+ _personal_info_to.issuer_address = self.test_issuer_address
+ _personal_info_to._personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "テスト太郎2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ } # latest data
+ db.add(_personal_info_to)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"to_address_name": "テスト太郎1"}, # test_from_address_1's name
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 1, "offset": None, "limit": None, "total": 2},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": {
+ "key_manager": "key_manager_test1",
+ "name": "テスト太郎1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "amount": 0,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: amount (EQUAL)
+ def test_normal_3_7_1(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_SHARE.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 10
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 20
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 30
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"amount": 20},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 1, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 20,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: amount (GTE)
+ def test_normal_3_7_2(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_SHARE.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 10
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 20
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 30
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"amount": 20, "amount_operator": 1},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 2, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 30,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 20,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: amount (LTE)
+ def test_normal_3_7_3(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_SHARE.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 10
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 20
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 30
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"amount": 20, "amount_operator": 2},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 2, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 10,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 20,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: source_event
+ def test_normal_3_8(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_SHARE.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_2
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_2
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 2
+ _idx_transfer.source_event = IDXTransferSourceEventType.UNLOCK.value
+ _idx_transfer.data = {"message": "unlock"}
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"source_event": IDXTransferSourceEventType.UNLOCK.value},
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 1, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.UNLOCK.value,
+ "data": {"message": "unlock"},
+ "block_timestamp": self.test_block_timestamp_str[2],
+ }
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # filter: data
+ def test_normal_3_9(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_SHARE.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_2
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_2
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 2
+ _idx_transfer.source_event = IDXTransferSourceEventType.UNLOCK.value
+ _idx_transfer.data = {"message": "unlock"}
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address), params={"data": "unlo"}
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 1, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.UNLOCK.value,
+ "data": {"message": "unlock"},
+ "block_timestamp": self.test_block_timestamp_str[2],
+ }
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # sort: block_timestamp ASC
+ def test_normal_4_1(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_SHARE.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ for i in range(0, 3):
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = i
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[i]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={
+ "sort_item": "block_timestamp",
+ "sort_order": 0,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 3, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 1,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 0,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # sort: from_address ASC
+ def test_normal_4_2(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_SHARE.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_2
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_2
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 2
+ _idx_transfer.source_event = IDXTransferSourceEventType.UNLOCK.value
+ _idx_transfer.data = {"message": "unlock"}
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={
+ "sort_item": "from_address",
+ "sort_order": 0,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 3, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.UNLOCK.value,
+ "data": {"message": "unlock"},
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_2,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 0,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_2,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 1,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # sort: to_address DESC
+ def test_normal_4_3(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_SHARE.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_2
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 2
+ _idx_transfer.source_event = IDXTransferSourceEventType.UNLOCK.value
+ _idx_transfer.data = {"message": "unlock"}
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={
+ "sort_item": "to_address",
+ "sort_order": 1,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 3, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_2,
+ "to_address_personal_information": None,
+ "amount": 0,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.UNLOCK.value,
+ "data": {"message": "unlock"},
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 1,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # sort: from_address_name DESC
+ def test_normal_4_4(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_SHARE.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_2
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ # prepare data: IDXPersonalInfo
+ _personal_info_from = IDXPersonalInfo()
+ _personal_info_from.account_address = self.test_from_address_1
+ _personal_info_from.issuer_address = self.test_issuer_address
+ _personal_info_from._personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "テスト太郎1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ } # latest data
+ db.add(_personal_info_from)
+
+ _personal_info_to = IDXPersonalInfo()
+ _personal_info_to.account_address = self.test_from_address_2
+ _personal_info_to.issuer_address = self.test_issuer_address
+ _personal_info_to._personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "テスト太郎2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ } # latest data
+ db.add(_personal_info_to)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={
+ "sort_item": "from_address_name",
+ "sort_order": 1,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 2, "offset": None, "limit": None, "total": 2},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_2,
+ "from_address_personal_information": {
+ "address": "address_test2",
+ "birth": "birth_test2",
+ "email": "email_test2",
+ "is_corporate": False,
+ "key_manager": "key_manager_test2",
+ "name": "テスト太郎2",
+ "postal_code": "postal_code_test2",
+ "tax_category": 10,
+ },
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 1,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": {
+ "address": "address_test1",
+ "birth": "birth_test1",
+ "email": "email_test1",
+ "is_corporate": False,
+ "key_manager": "key_manager_test1",
+ "name": "テスト太郎1",
+ "postal_code": "postal_code_test1",
+ "tax_category": 10,
+ },
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 0,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # sort: to_address_name DESC
+ def test_normal_4_5(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_SHARE.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 0
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_2
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ # prepare data: IDXPersonalInfo
+ _personal_info_from = IDXPersonalInfo()
+ _personal_info_from.account_address = self.test_to_address_1
+ _personal_info_from.issuer_address = self.test_issuer_address
+ _personal_info_from._personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "テスト太郎1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ } # latest data
+ db.add(_personal_info_from)
+
+ _personal_info_to = IDXPersonalInfo()
+ _personal_info_to.account_address = self.test_to_address_2
+ _personal_info_to.issuer_address = self.test_issuer_address
+ _personal_info_to._personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "テスト太郎2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ } # latest data
+ db.add(_personal_info_to)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={
+ "sort_item": "to_address_name",
+ "sort_order": 1,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 2, "offset": None, "limit": None, "total": 2},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_2,
+ "to_address_personal_information": {
+ "address": "address_test2",
+ "birth": "birth_test2",
+ "email": "email_test2",
+ "is_corporate": False,
+ "key_manager": "key_manager_test2",
+ "name": "テスト太郎2",
+ "postal_code": "postal_code_test2",
+ "tax_category": 10,
+ },
+ "amount": 1,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": {
+ "address": "address_test1",
+ "birth": "birth_test1",
+ "email": "email_test1",
+ "is_corporate": False,
+ "key_manager": "key_manager_test1",
+ "name": "テスト太郎1",
+ "postal_code": "postal_code_test1",
+ "tax_category": 10,
+ },
+ "amount": 0,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # sort: amount DESC
+ def test_normal_4_6(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_SHARE.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ # prepare data: IDXTransfer
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 1
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[0]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 2
+ _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
+ _idx_transfer.data = None
+ _idx_transfer.block_timestamp = self.test_block_timestamp[1]
+ db.add(_idx_transfer)
+
+ _idx_transfer = IDXTransfer()
+ _idx_transfer.transaction_hash = self.test_transaction_hash
+ _idx_transfer.token_address = self.test_token_address
+ _idx_transfer.from_address = self.test_from_address_1
+ _idx_transfer.to_address = self.test_to_address_1
+ _idx_transfer.amount = 2
+ _idx_transfer.source_event = IDXTransferSourceEventType.UNLOCK.value
+ _idx_transfer.data = {"message": "unlock"}
+ _idx_transfer.block_timestamp = self.test_block_timestamp[2]
+ db.add(_idx_transfer)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={
+ "sort_item": "amount",
+ "sort_order": 0,
+ },
+ )
+
+ # assertion
+ assert resp.status_code == 200
+ assumed_response = {
+ "result_set": {"count": 3, "offset": None, "limit": None, "total": 3},
+ "transfer_history": [
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 1,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[0],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.UNLOCK.value,
+ "data": {"message": "unlock"},
+ "block_timestamp": self.test_block_timestamp_str[2],
+ },
+ {
+ "transaction_hash": self.test_transaction_hash,
+ "token_address": self.test_token_address,
+ "from_address": self.test_from_address_1,
+ "from_address_personal_information": None,
+ "to_address": self.test_to_address_1,
+ "to_address_personal_information": None,
+ "amount": 2,
+ "source_event": IDXTransferSourceEventType.TRANSFER.value,
+ "data": None,
+ "block_timestamp": self.test_block_timestamp_str[1],
+ },
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ ###########################################################################
+ # Error Case
+ ###########################################################################
+
+ #
+ # token not found
+ def test_error_1(self, client, db):
+ # request target API
+ resp = client.get(self.base_url.format(self.test_token_address))
+
+ # assertion
+ assert resp.status_code == 404
+ assumed_response = {
+ "meta": {"code": 1, "title": "NotFound"},
+ "detail": "token not found",
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # processing token
+ def test_error_2(self, client, db):
+ # prepare data: Token
+ _token = Token()
+ _token.type = TokenType.IBET_SHARE.value
+ _token.tx_hash = self.test_transaction_hash
+ _token.issuer_address = self.test_issuer_address
+ _token.token_address = self.test_token_address
+ _token.abi = {}
+ _token.token_status = 0
+ _token.version = TokenVersion.V_24_06
+ db.add(_token)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(self.base_url.format(self.test_token_address))
+
+ # assertion
+ assert resp.status_code == 400
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "InvalidParameterError"},
+ "detail": "this token is temporarily unavailable",
+ }
+
+ #
+ # param error: sort_item
+ def test_error_3(self, client, db):
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address),
+ params={"sort_item": "block_timestamp12345"},
+ )
+
+ # assertion
+ assert resp.status_code == 422
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "type": "enum",
+ "loc": ["query", "sort_item"],
+ "msg": "Input should be 'block_timestamp', 'from_address', 'to_address', 'from_address_name', 'to_address_name' or 'amount'",
+ "input": "block_timestamp12345",
+ "ctx": {
+ "expected": "'block_timestamp', 'from_address', 'to_address', 'from_address_name', 'to_address_name' or 'amount'"
+ },
+ }
+ ],
+ }
+
+ #
+ # param error: sort_order(min)
+ def test_error_4(self, client, db):
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address), params={"sort_order": -1}
+ )
+
+ # assertion
+ assert resp.status_code == 422
+ assumed_response = {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "ctx": {"expected": "0 or 1"},
+ "input": "-1",
+ "loc": ["query", "sort_order"],
+ "msg": "Input should be 0 or 1",
+ "type": "enum",
+ }
+ ],
+ }
+ assert resp.json() == assumed_response
+
+ #
+ # param error: sort_order(max)
+ def test_error_5(self, client, db):
+ # request target API
+ resp = client.get(
+ self.base_url.format(self.test_token_address), params={"sort_order": 2}
+ )
+
+ # assertion
+ assert resp.status_code == 422
+ assumed_response = {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "ctx": {"expected": "0 or 1"},
+ "input": "2",
+ "loc": ["query", "sort_order"],
+ "msg": "Input should be 0 or 1",
+ "type": "enum",
+ }
+ ],
+ }
+ assert resp.json() == assumed_response
diff --git a/tests/app/test_token_holders_personal_info_GET.py b/tests/app/test_token_holders_personal_info_GET.py
new file mode 100644
index 00000000..52d28420
--- /dev/null
+++ b/tests/app/test_token_holders_personal_info_GET.py
@@ -0,0 +1,1115 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+from unittest import mock
+
+import pytest
+
+from app.model.db import IDXPersonalInfo
+from tests.account_config import config_eth_account
+
+
+class TestListTokenHoldersPersonalInfo:
+ # target API endpoint
+ url = "/token/holders/personal_info"
+
+ ###########################################################################
+ # Normal Case
+ ###########################################################################
+
+ #
+ # 0 record
+ def test_normal_1(self, client, db):
+ issuer_account = config_eth_account("user1")
+ issuer_address = issuer_account["address"]
+
+ # request target API
+ resp = client.get(
+ self.url,
+ headers={
+ "issuer-address": issuer_address,
+ },
+ )
+
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 0, "limit": None, "offset": None, "total": 0},
+ "personal_info": [],
+ }
+
+ #
+ # 1 record
+ @pytest.mark.freeze_time("2024-05-13 12:34:56")
+ def test_normal_2(self, client, db):
+ issuer_account = config_eth_account("user1")
+ issuer_address = issuer_account["address"]
+ account_address1 = "account_address1"
+
+ # prepare data
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address1
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ db.add(personal_info_idx)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.url,
+ headers={
+ "issuer-address": issuer_address,
+ },
+ )
+
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 1, "limit": None, "offset": None, "total": 1},
+ "personal_info": [
+ {
+ "id": 1,
+ "account_address": account_address1,
+ "personal_info": {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "created": "2024-05-13T21:34:56+09:00",
+ "modified": "2024-05-13T21:34:56+09:00",
+ }
+ ],
+ }
+
+ #
+ # Multiple records
+ # No search filter
+ @pytest.mark.freeze_time("2024-05-13 12:34:56")
+ def test_normal_3(self, client, db):
+ issuer_account = config_eth_account("user1")
+ issuer_address = issuer_account["address"]
+ account_address1 = "account_address1"
+ account_address2 = "account_address2"
+ account_address3 = "account_address3"
+
+ # prepare data
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address1
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ db.add(personal_info_idx)
+
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address2
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ # "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ db.add(personal_info_idx)
+
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address3
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ db.add(personal_info_idx)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.url,
+ headers={
+ "issuer-address": issuer_address,
+ },
+ )
+
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 3, "limit": None, "offset": None, "total": 3},
+ "personal_info": [
+ {
+ "id": 1,
+ "account_address": account_address1,
+ "personal_info": {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "created": "2024-05-13T21:34:56+09:00",
+ "modified": "2024-05-13T21:34:56+09:00",
+ },
+ {
+ "id": 2,
+ "account_address": account_address2,
+ "personal_info": {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "created": "2024-05-13T21:34:56+09:00",
+ "modified": "2024-05-13T21:34:56+09:00",
+ },
+ {
+ "id": 3,
+ "account_address": account_address3,
+ "personal_info": {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "created": "2024-05-13T21:34:56+09:00",
+ "modified": "2024-05-13T21:34:56+09:00",
+ },
+ ],
+ }
+
+ #
+ # Multiple records
+ # Search filter: account_address
+ def test_normal_4_1(self, client, db):
+ issuer_account = config_eth_account("user1")
+ issuer_address = issuer_account["address"]
+ account_address1 = "account_address1"
+ account_address2 = "account_address2"
+ account_address3 = "account_address3"
+
+ # prepare data
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address1
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ personal_info_idx.created = "2024-05-13 09:00:00"
+ personal_info_idx.modified = "2024-05-14 09:00:00"
+ db.add(personal_info_idx)
+
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address2
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ # "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ personal_info_idx.created = "2024-05-13 12:00:00"
+ personal_info_idx.modified = "2024-05-14 12:00:00"
+ db.add(personal_info_idx)
+
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address3
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ personal_info_idx.created = "2024-05-13 15:00:00"
+ personal_info_idx.modified = "2024-05-14 15:00:00"
+ db.add(personal_info_idx)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.url,
+ headers={
+ "issuer-address": issuer_address,
+ },
+ params={
+ "account_address": account_address2,
+ },
+ )
+
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 1, "limit": None, "offset": None, "total": 3},
+ "personal_info": [
+ {
+ "id": 2,
+ "account_address": account_address2,
+ "personal_info": {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "created": "2024-05-13T21:00:00+09:00",
+ "modified": "2024-05-14T21:00:00+09:00",
+ },
+ ],
+ }
+
+ #
+ # Multiple records
+ # Search filter: created_from, created_to
+ def test_normal_4_2(self, client, db):
+ issuer_account = config_eth_account("user1")
+ issuer_address = issuer_account["address"]
+ account_address1 = "account_address1"
+ account_address2 = "account_address2"
+ account_address3 = "account_address3"
+
+ # prepare data
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address1
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ personal_info_idx.created = "2024-05-13 09:00:00"
+ personal_info_idx.modified = "2024-05-14 09:00:00"
+ db.add(personal_info_idx)
+
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address2
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ # "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ personal_info_idx.created = "2024-05-13 12:00:00"
+ personal_info_idx.modified = "2024-05-14 12:00:00"
+ db.add(personal_info_idx)
+
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address3
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ personal_info_idx.created = "2024-05-13 15:00:00"
+ personal_info_idx.modified = "2024-05-14 15:00:00"
+ db.add(personal_info_idx)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.url,
+ headers={
+ "issuer-address": issuer_address,
+ },
+ params={
+ "created_from": "2024-05-13 21:00:00",
+ "created_to": "2024-05-13 21:00:00",
+ },
+ )
+
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 1, "limit": None, "offset": None, "total": 3},
+ "personal_info": [
+ {
+ "id": 2,
+ "account_address": account_address2,
+ "personal_info": {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "created": "2024-05-13T21:00:00+09:00",
+ "modified": "2024-05-14T21:00:00+09:00",
+ },
+ ],
+ }
+
+ #
+ # Multiple records
+ # Search filter: modified_from, modified_to
+ def test_normal_4_3(self, client, db):
+ issuer_account = config_eth_account("user1")
+ issuer_address = issuer_account["address"]
+ account_address1 = "account_address1"
+ account_address2 = "account_address2"
+ account_address3 = "account_address3"
+
+ # prepare data
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address1
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ personal_info_idx.created = "2024-05-13 09:00:00"
+ personal_info_idx.modified = "2024-05-14 09:00:00"
+ db.add(personal_info_idx)
+
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address2
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ # "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ personal_info_idx.created = "2024-05-13 12:00:00"
+ personal_info_idx.modified = "2024-05-14 12:00:00"
+ db.add(personal_info_idx)
+
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address3
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ personal_info_idx.created = "2024-05-13 15:00:00"
+ personal_info_idx.modified = "2024-05-14 15:00:00"
+ db.add(personal_info_idx)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.url,
+ headers={
+ "issuer-address": issuer_address,
+ },
+ params={
+ "modified_from": "2024-05-14 21:00:00",
+ "modified_to": "2024-05-14 21:00:00",
+ },
+ )
+
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 1, "limit": None, "offset": None, "total": 3},
+ "personal_info": [
+ {
+ "id": 2,
+ "account_address": account_address2,
+ "personal_info": {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "created": "2024-05-13T21:00:00+09:00",
+ "modified": "2024-05-14T21:00:00+09:00",
+ },
+ ],
+ }
+
+ #
+ # Sort
+ # - sort_item: None(created)
+ # - sort_order: DESC
+ def test_normal_5_1(self, client, db):
+ issuer_account = config_eth_account("user1")
+ issuer_address = issuer_account["address"]
+ account_address1 = "account_address1"
+ account_address2 = "account_address2"
+ account_address3 = "account_address3"
+
+ # prepare data
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address1
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ personal_info_idx.created = "2023-10-23 00:00:00"
+ personal_info_idx.modified = "2023-10-24 00:00:00"
+ db.add(personal_info_idx)
+
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address2
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ # "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ personal_info_idx.created = "2023-10-23 00:00:01"
+ personal_info_idx.modified = "2023-10-24 00:00:01"
+ db.add(personal_info_idx)
+
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address3
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ personal_info_idx.created = "2023-10-23 00:00:02"
+ personal_info_idx.modified = "2023-10-24 00:00:02"
+ db.add(personal_info_idx)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.url,
+ headers={
+ "issuer-address": issuer_address,
+ },
+ params={"sort_order": 1},
+ )
+
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 3, "limit": None, "offset": None, "total": 3},
+ "personal_info": [
+ {
+ "id": 3,
+ "account_address": account_address3,
+ "personal_info": {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "created": "2023-10-23T09:00:02+09:00",
+ "modified": "2023-10-24T09:00:02+09:00",
+ },
+ {
+ "id": 2,
+ "account_address": account_address2,
+ "personal_info": {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "created": "2023-10-23T09:00:01+09:00",
+ "modified": "2023-10-24T09:00:01+09:00",
+ },
+ {
+ "id": 1,
+ "account_address": account_address1,
+ "personal_info": {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "created": "2023-10-23T09:00:00+09:00",
+ "modified": "2023-10-24T09:00:00+09:00",
+ },
+ ],
+ }
+
+ #
+ # Sort
+ # - sort_item: account_address
+ # - sort_order: ASC
+ def test_normal_5_2(self, client, db):
+ issuer_account = config_eth_account("user1")
+ issuer_address = issuer_account["address"]
+ account_address1 = "account_address1"
+ account_address2 = "account_address2"
+ account_address3 = "account_address3"
+
+ # prepare data
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address1
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ personal_info_idx.created = "2023-10-23 00:00:02"
+ db.add(personal_info_idx)
+
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address2
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ # "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ personal_info_idx.created = "2023-10-23 00:00:01"
+ db.add(personal_info_idx)
+
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address3
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ personal_info_idx.created = "2023-10-23 00:00:00"
+ db.add(personal_info_idx)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.url,
+ headers={
+ "issuer-address": issuer_address,
+ },
+ params={"sort_item": "account_address", "sort_order": 0},
+ )
+
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 3, "limit": None, "offset": None, "total": 3},
+ "personal_info": [
+ {
+ "id": 1,
+ "account_address": account_address1,
+ "personal_info": {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "created": mock.ANY,
+ "modified": mock.ANY,
+ },
+ {
+ "id": 2,
+ "account_address": account_address2,
+ "personal_info": {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "created": mock.ANY,
+ "modified": mock.ANY,
+ },
+ {
+ "id": 3,
+ "account_address": account_address3,
+ "personal_info": {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "created": mock.ANY,
+ "modified": mock.ANY,
+ },
+ ],
+ }
+
+ #
+ # Sort
+ # - sort_item: modified
+ # - sort_order: ASC
+ def test_normal_5_3(self, client, db):
+ issuer_account = config_eth_account("user1")
+ issuer_address = issuer_account["address"]
+ account_address1 = "account_address1"
+ account_address2 = "account_address2"
+ account_address3 = "account_address3"
+
+ # prepare data
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address1
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ personal_info_idx.created = "2023-10-23 00:00:00"
+ personal_info_idx.modified = "2023-10-24 00:00:02"
+ db.add(personal_info_idx)
+
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address2
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ # "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ personal_info_idx.created = "2023-10-23 00:00:01"
+ personal_info_idx.modified = "2023-10-24 00:00:01"
+ db.add(personal_info_idx)
+
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address3
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ personal_info_idx.created = "2023-10-23 00:00:02"
+ personal_info_idx.modified = "2023-10-24 00:00:00"
+ db.add(personal_info_idx)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.url,
+ headers={
+ "issuer-address": issuer_address,
+ },
+ params={"sort_item": "modified", "sort_order": 0},
+ )
+
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 3, "limit": None, "offset": None, "total": 3},
+ "personal_info": [
+ {
+ "id": 3,
+ "account_address": account_address3,
+ "personal_info": {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "created": "2023-10-23T09:00:02+09:00",
+ "modified": "2023-10-24T09:00:00+09:00",
+ },
+ {
+ "id": 2,
+ "account_address": account_address2,
+ "personal_info": {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "created": "2023-10-23T09:00:01+09:00",
+ "modified": "2023-10-24T09:00:01+09:00",
+ },
+ {
+ "id": 1,
+ "account_address": account_address1,
+ "personal_info": {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "created": "2023-10-23T09:00:00+09:00",
+ "modified": "2023-10-24T09:00:02+09:00",
+ },
+ ],
+ }
+
+ #
+ # Pagination
+ @pytest.mark.freeze_time("2024-05-13 12:34:56")
+ def test_normal_6(self, client, db):
+ issuer_account = config_eth_account("user1")
+ issuer_address = issuer_account["address"]
+ account_address1 = "account_address1"
+ account_address2 = "account_address2"
+ account_address3 = "account_address3"
+
+ # prepare data
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address1
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ db.add(personal_info_idx)
+
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address2
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ # "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ db.add(personal_info_idx)
+
+ personal_info_idx = IDXPersonalInfo()
+ personal_info_idx.issuer_address = issuer_address
+ personal_info_idx.account_address = account_address3
+ personal_info_idx.personal_info = {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ db.add(personal_info_idx)
+
+ db.commit()
+
+ # request target API
+ req_param = {"limit": 2, "offset": 1}
+ resp = client.get(
+ self.url,
+ params=req_param,
+ headers={
+ "issuer-address": issuer_address,
+ },
+ )
+
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 3, "limit": 2, "offset": 1, "total": 3},
+ "personal_info": [
+ {
+ "id": 2,
+ "account_address": account_address2,
+ "personal_info": {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "created": "2024-05-13T21:34:56+09:00",
+ "modified": "2024-05-13T21:34:56+09:00",
+ },
+ {
+ "id": 3,
+ "account_address": account_address3,
+ "personal_info": {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": None,
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "created": "2024-05-13T21:34:56+09:00",
+ "modified": "2024-05-13T21:34:56+09:00",
+ },
+ ],
+ }
+
+ ###########################################################################
+ # Error Case
+ ###########################################################################
+
+ #
+ # RequestValidationError: created_from, created_to, modified_from, modified_to
+ def test_error_1_1(self, client, db):
+ issuer_account = config_eth_account("user1")
+ issuer_address = issuer_account["address"]
+
+ # request target API
+ resp = client.get(
+ self.url,
+ headers={
+ "issuer-address": issuer_address,
+ },
+ params={
+ "created_from": "invalid_date",
+ "created_to": "invalid_date",
+ "modified_from": "invalid_date",
+ "modified_to": "invalid_date",
+ },
+ )
+
+ assert resp.status_code == 422
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "type": "value_error",
+ "loc": ["query", "created_from"],
+ "msg": "Value error, value must be of string datetime format",
+ "input": "invalid_date",
+ "ctx": {"error": {}},
+ },
+ {
+ "type": "value_error",
+ "loc": ["query", "created_to"],
+ "msg": "Value error, value must be of string datetime format",
+ "input": "invalid_date",
+ "ctx": {"error": {}},
+ },
+ {
+ "type": "value_error",
+ "loc": ["query", "modified_from"],
+ "msg": "Value error, value must be of string datetime format",
+ "input": "invalid_date",
+ "ctx": {"error": {}},
+ },
+ {
+ "type": "value_error",
+ "loc": ["query", "modified_to"],
+ "msg": "Value error, value must be of string datetime format",
+ "input": "invalid_date",
+ "ctx": {"error": {}},
+ },
+ ],
+ }
+
+ #
+ # RequestValidationError: sort_item, sort_order
+ def test_error_1_2(self, client, db):
+ issuer_account = config_eth_account("user1")
+ issuer_address = issuer_account["address"]
+
+ # request target API
+ resp = client.get(
+ self.url,
+ headers={
+ "issuer-address": issuer_address,
+ },
+ params={"sort_item": "invalid_sort_item", "sort_order": 2},
+ )
+
+ assert resp.status_code == 422
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "type": "enum",
+ "loc": ["query", "sort_item"],
+ "msg": "Input should be 'account_address', 'created' or 'modified'",
+ "input": "invalid_sort_item",
+ "ctx": {"expected": "'account_address', 'created' or 'modified'"},
+ },
+ {
+ "type": "enum",
+ "loc": ["query", "sort_order"],
+ "msg": "Input should be 0 or 1",
+ "input": "2",
+ "ctx": {"expected": "0 or 1"},
+ },
+ ],
+ }
diff --git a/tests/app/test_token_holders_personal_info_history_GET.py b/tests/app/test_token_holders_personal_info_history_GET.py
new file mode 100644
index 00000000..866b89b6
--- /dev/null
+++ b/tests/app/test_token_holders_personal_info_history_GET.py
@@ -0,0 +1,829 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+from app.model.db import IDXPersonalInfoHistory, PersonalInfoEventType
+from tests.account_config import config_eth_account
+
+
+class TestListTokenHoldersPersonalInfoHistory:
+ # target API endpoint
+ url = "/token/holders/personal_info/history"
+
+ test_issuer_address_1 = config_eth_account("user1")["address"]
+ test_issuer_address_2 = config_eth_account("user2")["address"]
+ test_account_address_1 = config_eth_account("user3")["address"]
+ test_account_address_2 = config_eth_account("user4")["address"]
+
+ ###########################################################################
+ # Normal Case
+ ###########################################################################
+
+ #
+ # 0 record
+ def test_normal_1(self, client, db):
+ # Request target API
+ resp = client.get(
+ self.url,
+ headers={
+ "issuer-address": self.test_issuer_address_1,
+ },
+ )
+
+ # Assertion
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 0, "limit": None, "offset": None, "total": 0},
+ "personal_info": [],
+ }
+
+ #
+ # Multiple records
+ # No search filter
+ def test_normal_2(self, client, db):
+ # Prepare data
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_1
+ history.account_address = self.test_account_address_1
+ history.event_type = PersonalInfoEventType.REGISTER
+ history.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-12 23:59:59"
+ history.created = "2024-05-13 00:00:00"
+ db.add(history)
+
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_1
+ history.account_address = self.test_account_address_1
+ history.event_type = PersonalInfoEventType.MODIFY
+ history.personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-13 23:59:59"
+ history.created = "2024-05-14 00:00:00"
+ db.add(history)
+
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_2
+ history.account_address = self.test_account_address_2
+ history.event_type = PersonalInfoEventType.REGISTER
+ history.personal_info = {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": "birth_test3",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-13 23:59:59"
+ history.created = "2024-05-14 00:00:00"
+ db.add(history)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.url,
+ headers={
+ "issuer-address": self.test_issuer_address_1,
+ },
+ )
+
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 2, "limit": None, "offset": None, "total": 2},
+ "personal_info": [
+ {
+ "id": 1,
+ "account_address": self.test_account_address_1,
+ "event_type": "register",
+ "personal_info": {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "block_timestamp": "2024-05-13T08:59:59+09:00",
+ "created": "2024-05-13T09:00:00+09:00",
+ },
+ {
+ "id": 2,
+ "account_address": self.test_account_address_1,
+ "event_type": "modify",
+ "personal_info": {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "block_timestamp": "2024-05-14T08:59:59+09:00",
+ "created": "2024-05-14T09:00:00+09:00",
+ },
+ ],
+ }
+
+ #
+ # Multiple records
+ # Search filter: account_address
+ def test_normal_3_1(self, client, db):
+ # Prepare data
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_1
+ history.account_address = self.test_account_address_1
+ history.event_type = PersonalInfoEventType.REGISTER
+ history.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-12 23:59:59"
+ history.created = "2024-05-13 00:00:00"
+ db.add(history)
+
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_1
+ history.account_address = self.test_account_address_1
+ history.event_type = PersonalInfoEventType.MODIFY
+ history.personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-13 23:59:59"
+ history.created = "2024-05-14 00:00:00"
+ db.add(history)
+
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_1
+ history.account_address = self.test_account_address_2
+ history.event_type = PersonalInfoEventType.REGISTER
+ history.personal_info = {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": "birth_test3",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-13 23:59:59"
+ history.created = "2024-05-14 00:00:00"
+ db.add(history)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.url,
+ headers={
+ "issuer-address": self.test_issuer_address_1,
+ },
+ params={"account_address": self.test_account_address_1},
+ )
+
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 2, "limit": None, "offset": None, "total": 3},
+ "personal_info": [
+ {
+ "id": 1,
+ "account_address": self.test_account_address_1,
+ "event_type": "register",
+ "personal_info": {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "block_timestamp": "2024-05-13T08:59:59+09:00",
+ "created": "2024-05-13T09:00:00+09:00",
+ },
+ {
+ "id": 2,
+ "account_address": self.test_account_address_1,
+ "event_type": "modify",
+ "personal_info": {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "block_timestamp": "2024-05-14T08:59:59+09:00",
+ "created": "2024-05-14T09:00:00+09:00",
+ },
+ ],
+ }
+
+ #
+ # Multiple records
+ # Search filter: event_type
+ def test_normal_3_2(self, client, db):
+ # Prepare data
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_1
+ history.account_address = self.test_account_address_1
+ history.event_type = PersonalInfoEventType.REGISTER
+ history.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-12 23:59:59"
+ history.created = "2024-05-13 00:00:00"
+ db.add(history)
+
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_1
+ history.account_address = self.test_account_address_1
+ history.event_type = PersonalInfoEventType.MODIFY
+ history.personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-14 00:00:00"
+ history.created = "2024-05-14 00:00:01"
+ db.add(history)
+
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_1
+ history.account_address = self.test_account_address_1
+ history.event_type = PersonalInfoEventType.REGISTER
+ history.personal_info = {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": "birth_test3",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-14 00:00:01"
+ history.created = "2024-05-14 00:00:02"
+ db.add(history)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.url,
+ headers={
+ "issuer-address": self.test_issuer_address_1,
+ },
+ params={
+ "event_type": "modify",
+ },
+ )
+
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 1, "limit": None, "offset": None, "total": 3},
+ "personal_info": [
+ {
+ "id": 2,
+ "account_address": self.test_account_address_1,
+ "event_type": "modify",
+ "personal_info": {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "block_timestamp": "2024-05-14T09:00:00+09:00",
+ "created": "2024-05-14T09:00:01+09:00",
+ },
+ ],
+ }
+
+ #
+ # Multiple records
+ # Search filter: created_from, created_to
+ def test_normal_3_3(self, client, db):
+ # Prepare data
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_1
+ history.account_address = self.test_account_address_1
+ history.event_type = PersonalInfoEventType.REGISTER
+ history.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-12 23:59:59"
+ history.created = "2024-05-13 00:00:00"
+ db.add(history)
+
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_1
+ history.account_address = self.test_account_address_1
+ history.event_type = PersonalInfoEventType.MODIFY
+ history.personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-14 00:00:00"
+ history.created = "2024-05-14 00:00:01"
+ db.add(history)
+
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_1
+ history.account_address = self.test_account_address_1
+ history.event_type = PersonalInfoEventType.REGISTER
+ history.personal_info = {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": "birth_test3",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-14 00:00:01"
+ history.created = "2024-05-14 00:00:02"
+ db.add(history)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.url,
+ headers={
+ "issuer-address": self.test_issuer_address_1,
+ },
+ params={
+ "created_from": "2024-05-14 09:00:01",
+ "created_to": "2024-05-14 09:00:01",
+ },
+ )
+
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 1, "limit": None, "offset": None, "total": 3},
+ "personal_info": [
+ {
+ "id": 2,
+ "account_address": self.test_account_address_1,
+ "event_type": "modify",
+ "personal_info": {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "block_timestamp": "2024-05-14T09:00:00+09:00",
+ "created": "2024-05-14T09:00:01+09:00",
+ },
+ ],
+ }
+
+ #
+ # Multiple records
+ # Search filter: block_timestamp_from, block_timestamp_to
+ def test_normal_3_4(self, client, db):
+ # Prepare data
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_1
+ history.account_address = self.test_account_address_1
+ history.event_type = PersonalInfoEventType.REGISTER
+ history.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-12 23:59:59"
+ history.created = "2024-05-13 00:00:00"
+ db.add(history)
+
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_1
+ history.account_address = self.test_account_address_1
+ history.event_type = PersonalInfoEventType.MODIFY
+ history.personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-14 00:00:00"
+ history.created = "2024-05-14 00:00:01"
+ db.add(history)
+
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_1
+ history.account_address = self.test_account_address_1
+ history.event_type = PersonalInfoEventType.REGISTER
+ history.personal_info = {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": "birth_test3",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-14 00:00:01"
+ history.created = "2024-05-14 00:00:02"
+ db.add(history)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.url,
+ headers={
+ "issuer-address": self.test_issuer_address_1,
+ },
+ params={
+ "block_timestamp_from": "2024-05-14 09:00:00",
+ "block_timestamp_to": "2024-05-14 09:00:00",
+ },
+ )
+
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 1, "limit": None, "offset": None, "total": 3},
+ "personal_info": [
+ {
+ "id": 2,
+ "account_address": self.test_account_address_1,
+ "event_type": "modify",
+ "personal_info": {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "block_timestamp": "2024-05-14T09:00:00+09:00",
+ "created": "2024-05-14T09:00:01+09:00",
+ },
+ ],
+ }
+
+ #
+ # Multiple records
+ # Sort: block_timestamp, DESC
+ def test_normal_4(self, client, db):
+ # Prepare data
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_1
+ history.account_address = self.test_account_address_1
+ history.event_type = PersonalInfoEventType.REGISTER
+ history.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-13 23:59:59"
+ history.created = "2024-05-14 00:00:00"
+ db.add(history)
+
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_1
+ history.account_address = self.test_account_address_1
+ history.event_type = PersonalInfoEventType.MODIFY
+ history.personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-14 00:00:00"
+ history.created = "2024-05-14 00:00:01"
+ db.add(history)
+
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_1
+ history.account_address = self.test_account_address_1
+ history.event_type = PersonalInfoEventType.REGISTER
+ history.personal_info = {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": "birth_test3",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-14 00:00:01"
+ history.created = "2024-05-14 00:00:02"
+ db.add(history)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.url,
+ headers={
+ "issuer-address": self.test_issuer_address_1,
+ },
+ params={
+ "sort_order": 1,
+ },
+ )
+
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 3, "limit": None, "offset": None, "total": 3},
+ "personal_info": [
+ {
+ "id": 3,
+ "account_address": self.test_account_address_1,
+ "event_type": "register",
+ "personal_info": {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": "birth_test3",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "block_timestamp": "2024-05-14T09:00:01+09:00",
+ "created": "2024-05-14T09:00:02+09:00",
+ },
+ {
+ "id": 2,
+ "account_address": self.test_account_address_1,
+ "event_type": "modify",
+ "personal_info": {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "block_timestamp": "2024-05-14T09:00:00+09:00",
+ "created": "2024-05-14T09:00:01+09:00",
+ },
+ {
+ "id": 1,
+ "account_address": self.test_account_address_1,
+ "event_type": "register",
+ "personal_info": {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "block_timestamp": "2024-05-14T08:59:59+09:00",
+ "created": "2024-05-14T09:00:00+09:00",
+ },
+ ],
+ }
+
+ #
+ # Multiple records
+ # Pagination: offset, limit
+ def test_normal_5(self, client, db):
+ # Prepare data
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_1
+ history.account_address = self.test_account_address_1
+ history.event_type = PersonalInfoEventType.REGISTER
+ history.personal_info = {
+ "key_manager": "key_manager_test1",
+ "name": "name_test1",
+ "postal_code": "postal_code_test1",
+ "address": "address_test1",
+ "email": "email_test1",
+ "birth": "birth_test1",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-12 23:59:59"
+ history.created = "2024-05-14 00:00:00"
+ db.add(history)
+
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_1
+ history.account_address = self.test_account_address_1
+ history.event_type = PersonalInfoEventType.MODIFY
+ history.personal_info = {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-14 00:00:00"
+ history.created = "2024-05-14 00:00:01"
+ db.add(history)
+
+ history = IDXPersonalInfoHistory()
+ history.issuer_address = self.test_issuer_address_1
+ history.account_address = self.test_account_address_1
+ history.event_type = PersonalInfoEventType.REGISTER
+ history.personal_info = {
+ "key_manager": "key_manager_test3",
+ "name": "name_test3",
+ "postal_code": "postal_code_test3",
+ "address": "address_test3",
+ "email": "email_test3",
+ "birth": "birth_test3",
+ "is_corporate": False,
+ "tax_category": 10,
+ }
+ history.block_timestamp = "2024-05-14 00:00:01"
+ history.created = "2024-05-14 00:00:02"
+ db.add(history)
+
+ db.commit()
+
+ # request target API
+ resp = client.get(
+ self.url,
+ headers={
+ "issuer-address": self.test_issuer_address_1,
+ },
+ params={"offset": 1, "limit": 1},
+ )
+
+ assert resp.status_code == 200
+ assert resp.json() == {
+ "result_set": {"count": 3, "limit": 1, "offset": 1, "total": 3},
+ "personal_info": [
+ {
+ "id": 2,
+ "account_address": self.test_account_address_1,
+ "event_type": "modify",
+ "personal_info": {
+ "key_manager": "key_manager_test2",
+ "name": "name_test2",
+ "postal_code": "postal_code_test2",
+ "address": "address_test2",
+ "email": "email_test2",
+ "birth": "birth_test2",
+ "is_corporate": False,
+ "tax_category": 10,
+ },
+ "block_timestamp": "2024-05-14T09:00:00+09:00",
+ "created": "2024-05-14T09:00:01+09:00",
+ },
+ ],
+ }
+
+ ###########################################################################
+ # Error Case
+ ###########################################################################
+
+ #
+ # RequestValidationError: created_from, created_to
+ def test_error_1(self, client, db):
+ # Request target API
+ resp = client.get(
+ self.url,
+ headers={
+ "issuer-address": self.test_issuer_address_1,
+ },
+ params={
+ "created_from": "invalid_date",
+ "created_to": "invalid_date",
+ },
+ )
+
+ # Assertion
+ assert resp.status_code == 422
+ assert resp.json() == {
+ "meta": {"code": 1, "title": "RequestValidationError"},
+ "detail": [
+ {
+ "type": "value_error",
+ "loc": ["query", "created_from"],
+ "msg": "Value error, value must be of string datetime format",
+ "input": "invalid_date",
+ "ctx": {"error": {}},
+ },
+ {
+ "type": "value_error",
+ "loc": ["query", "created_to"],
+ "msg": "Value error, value must be of string datetime format",
+ "input": "invalid_date",
+ "ctx": {"error": {}},
+ },
+ ],
+ }
diff --git a/tests/test_app_routers_token_holders_{token_address}_GET.py b/tests/app/test_token_holders_{token_address}_GET.py
similarity index 96%
rename from tests/test_app_routers_token_holders_{token_address}_GET.py
rename to tests/app/test_token_holders_{token_address}_GET.py
index 806530c7..6b3ec4bc 100644
--- a/tests/test_app_routers_token_holders_{token_address}_GET.py
+++ b/tests/app/test_token_holders_{token_address}_GET.py
@@ -18,6 +18,7 @@
"""
import uuid
+from datetime import datetime
from unittest import mock
from app.model.db import (
@@ -52,7 +53,7 @@ def test_normal_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -80,7 +81,7 @@ def test_normal_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
token_holder_list1 = TokenHoldersList()
@@ -123,7 +124,7 @@ def test_normal_3_1(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
token_holder_list1 = TokenHoldersList()
@@ -225,7 +226,7 @@ def test_normal_3_2(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
@@ -332,7 +333,7 @@ def test_normal_3_3(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
token_holder_list1 = TokenHoldersList()
@@ -406,7 +407,7 @@ def test_normal_4(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
token_holder_list1 = TokenHoldersList()
@@ -414,6 +415,7 @@ def test_normal_4(self, client, db):
token_holder_list1.list_id = str(uuid.uuid4())
token_holder_list1.block_number = 100
token_holder_list1.batch_status = TokenHolderBatchStatus.PENDING.value
+ token_holder_list1.created = datetime(2024, 1, 2, 3, 4, 51)
db.add(token_holder_list1)
token_holder_list2 = TokenHoldersList()
@@ -421,6 +423,7 @@ def test_normal_4(self, client, db):
token_holder_list2.list_id = str(uuid.uuid4())
token_holder_list2.block_number = 200
token_holder_list2.batch_status = TokenHolderBatchStatus.FAILED.value
+ token_holder_list2.created = datetime(2024, 1, 2, 3, 4, 52)
db.add(token_holder_list2)
token_holder_list3 = TokenHoldersList()
@@ -428,6 +431,7 @@ def test_normal_4(self, client, db):
token_holder_list3.list_id = str(uuid.uuid4())
token_holder_list3.block_number = 300
token_holder_list3.batch_status = TokenHolderBatchStatus.FAILED.value
+ token_holder_list3.created = datetime(2024, 1, 2, 3, 4, 53)
db.add(token_holder_list3)
token_holder_list4 = TokenHoldersList()
@@ -435,6 +439,7 @@ def test_normal_4(self, client, db):
token_holder_list4.list_id = str(uuid.uuid4())
token_holder_list4.block_number = 400
token_holder_list4.batch_status = TokenHolderBatchStatus.DONE.value
+ token_holder_list4.created = datetime(2024, 1, 2, 3, 4, 54)
db.add(token_holder_list4)
token_holder_list5 = TokenHoldersList()
@@ -442,6 +447,7 @@ def test_normal_4(self, client, db):
token_holder_list5.list_id = str(uuid.uuid4())
token_holder_list5.block_number = 500
token_holder_list5.batch_status = TokenHolderBatchStatus.DONE.value
+ token_holder_list5.created = datetime(2024, 1, 2, 3, 4, 55)
db.add(token_holder_list5)
db.commit()
@@ -483,7 +489,7 @@ def test_normal_5(self, client, db):
token.issuer_address = issuer_address
token.token_address = token_address
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
token_holder_list1 = TokenHoldersList()
@@ -627,7 +633,7 @@ def test_error_3(self, client, db):
token.token_address = token_address
token.token_status = 0
token.abi = ""
- token.version = TokenVersion.V_22_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_app_routers_token_holders_{token_address}_collection_POST.py b/tests/app/test_token_holders_{token_address}_collection_POST.py
similarity index 96%
rename from tests/test_app_routers_token_holders_{token_address}_collection_POST.py
rename to tests/app/test_token_holders_{token_address}_collection_POST.py
index 86eba5ed..b7ae2318 100644
--- a/tests/test_app_routers_token_holders_{token_address}_collection_POST.py
+++ b/tests/app/test_token_holders_{token_address}_collection_POST.py
@@ -24,7 +24,7 @@
import pytest
from sqlalchemy import select
from web3 import Web3
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
import config
from app.model.db import (
@@ -37,7 +37,7 @@
from tests.account_config import config_eth_account
web3 = Web3(Web3.HTTPProvider(config.WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
class TestAppRoutersHoldersTokenAddressCollectionPOST:
@@ -64,7 +64,7 @@ async def test_normal_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -116,7 +116,7 @@ async def test_normal_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -184,7 +184,7 @@ async def test_error_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -228,7 +228,7 @@ async def test_error_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -266,7 +266,7 @@ async def test_error_3(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -311,7 +311,7 @@ def test_error_4(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -355,7 +355,7 @@ def test_error_5(self, client, db):
_token1.issuer_address = issuer_address
_token1.token_address = token_address1
_token1.abi = {}
- _token1.version = TokenVersion.V_22_12
+ _token1.version = TokenVersion.V_24_06
db.add(_token1)
db.commit()
@@ -391,7 +391,7 @@ def test_error_5(self, client, db):
_token2.issuer_address = issuer_address
_token2.token_address = token_address2
_token2.abi = {}
- _token2.version = TokenVersion.V_22_12
+ _token2.version = TokenVersion.V_24_06
db.add(_token2)
db.commit()
@@ -432,7 +432,7 @@ async def test_error_6(self, client, db):
_token.token_address = token_address
_token.abi = {}
_token.token_status = 0
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -471,7 +471,7 @@ async def test_error_7(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
diff --git a/tests/test_app_routers_token_holders_{token_address}_collection_{collection_id}_GET.py b/tests/app/test_token_holders_{token_address}_collection_{collection_id}_GET.py
similarity index 96%
rename from tests/test_app_routers_token_holders_{token_address}_collection_{collection_id}_GET.py
rename to tests/app/test_token_holders_{token_address}_collection_{collection_id}_GET.py
index 8f147eea..0d897d73 100644
--- a/tests/test_app_routers_token_holders_{token_address}_collection_{collection_id}_GET.py
+++ b/tests/app/test_token_holders_{token_address}_collection_{collection_id}_GET.py
@@ -22,7 +22,7 @@
from sqlalchemy import select
from web3 import Web3
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
import config
from app.model.db import (
@@ -36,7 +36,7 @@
from tests.account_config import config_eth_account
web3 = Web3(Web3.HTTPProvider(config.WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
class TestAppRoutersHoldersTokenAddressCollectionIdGET:
@@ -64,7 +64,7 @@ def test_normal_1(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
list_id = str(uuid.uuid4())
@@ -107,7 +107,7 @@ def test_normal_2(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
list_id = str(uuid.uuid4())
@@ -189,7 +189,7 @@ def test_error_2(self, client, db):
# set status pending
_token.token_status = 0
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
list_id = str(uuid.uuid4())
@@ -231,7 +231,7 @@ def test_error_3(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
list_id = str(uuid.uuid4())
@@ -273,7 +273,7 @@ def test_error_4(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
db.commit()
@@ -310,7 +310,7 @@ def test_error_5(self, client, db):
_token1.issuer_address = issuer_address
_token1.token_address = token_address1
_token1.abi = {}
- _token1.version = TokenVersion.V_22_12
+ _token1.version = TokenVersion.V_24_06
db.add(_token1)
_token2 = Token()
@@ -319,7 +319,7 @@ def test_error_5(self, client, db):
_token2.issuer_address = issuer_address
_token2.token_address = token_address2
_token2.abi = {}
- _token2.version = TokenVersion.V_22_12
+ _token2.version = TokenVersion.V_24_06
db.add(_token2)
list_id = str(uuid.uuid4())
@@ -362,7 +362,7 @@ def test_error_6(self, client, db):
_token.issuer_address = issuer_address
_token.token_address = token_address
_token.abi = {}
- _token.version = TokenVersion.V_22_12
+ _token.version = TokenVersion.V_24_06
db.add(_token)
list_id = str(uuid.uuid4())
diff --git a/tests/test_utils_asynccontract_utils.py b/tests/app/utils/test_asynccontract_utils.py
similarity index 98%
rename from tests/test_utils_asynccontract_utils.py
rename to tests/app/utils/test_asynccontract_utils.py
index 29a72727..dc019817 100755
--- a/tests/test_utils_asynccontract_utils.py
+++ b/tests/app/utils/test_asynccontract_utils.py
@@ -26,7 +26,7 @@
from sqlalchemy.orm import Session
from web3 import Web3
from web3.exceptions import ContractLogicError, Web3Exception
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
from app.exceptions import ContractRevertError, SendTransactionError
from app.model.db import TransactionLock
@@ -35,7 +35,7 @@
from tests.account_config import config_eth_account
web3 = Web3(Web3.HTTPProvider(WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"
@@ -276,7 +276,7 @@ async def test_normal_1(self, db: Session):
transaction=tx, private_key=self.private_key
)
- assert rtn_tx_hash == rtn_receipt["transactionHash"].hex()
+ assert rtn_tx_hash == rtn_receipt["transactionHash"].to_0x_hex()
assert rtn_receipt["status"] == 1
assert rtn_receipt["to"] is None
assert rtn_receipt["from"] == self.test_account["address"]
@@ -454,7 +454,7 @@ async def test_normal_1(self, db: Session):
)
# Send Transaction
- tx_hash = web3.eth.send_raw_transaction(signed_tx.rawTransaction.hex())
+ tx_hash = web3.eth.send_raw_transaction(signed_tx.raw_transaction.to_0x_hex())
tx_receipt = web3.eth.wait_for_transaction_receipt(
transaction_hash=tx_hash, timeout=10
)
diff --git a/tests/test_utils_check_utils.py b/tests/app/utils/test_check_utils.py
similarity index 100%
rename from tests/test_utils_check_utils.py
rename to tests/app/utils/test_check_utils.py
diff --git a/tests/test_utils_contract_utils.py b/tests/app/utils/test_contract_utils.py
similarity index 98%
rename from tests/test_utils_contract_utils.py
rename to tests/app/utils/test_contract_utils.py
index 54c65de0..8aa5e547 100755
--- a/tests/test_utils_contract_utils.py
+++ b/tests/app/utils/test_contract_utils.py
@@ -26,7 +26,7 @@
from sqlalchemy.orm import Session
from web3 import Web3
from web3.exceptions import ContractLogicError, Web3Exception
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
from app.exceptions import ContractRevertError, SendTransactionError
from app.model.db import TransactionLock
@@ -35,7 +35,7 @@
from tests.account_config import config_eth_account
web3 = Web3(Web3.HTTPProvider(WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"
@@ -266,7 +266,7 @@ def test_normal_1(self, db: Session):
transaction=tx, private_key=self.private_key
)
- assert rtn_tx_hash == rtn_receipt["transactionHash"].hex()
+ assert rtn_tx_hash == rtn_receipt["transactionHash"].to_0x_hex()
assert rtn_receipt["status"] == 1
assert rtn_receipt["to"] is None
assert rtn_receipt["from"] == self.test_account["address"]
@@ -438,7 +438,7 @@ def test_normal_1(self, db: Session):
)
# Send Transaction
- tx_hash = web3.eth.send_raw_transaction(signed_tx.rawTransaction.hex())
+ tx_hash = web3.eth.send_raw_transaction(signed_tx.raw_transaction.to_0x_hex())
tx_receipt = web3.eth.wait_for_transaction_receipt(
transaction_hash=tx_hash, timeout=10
)
diff --git a/tests/app/utils/test_ledger_utils.py b/tests/app/utils/test_ledger_utils.py
new file mode 100644
index 00000000..afbb34c5
--- /dev/null
+++ b/tests/app/utils/test_ledger_utils.py
@@ -0,0 +1,2813 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+from datetime import datetime
+
+import pytest
+import pytz
+from eth_keyfile import decode_keyfile_json
+from sqlalchemy import select
+from web3 import Web3
+from web3.middleware import ExtraDataToPOAMiddleware
+
+from app.model.blockchain import (
+ IbetShareContract,
+ IbetStraightBondContract,
+ PersonalInfoContract,
+)
+from app.model.blockchain.tx_params.ibet_share import (
+ UpdateParams as IbetShareUpdateParams,
+)
+from app.model.blockchain.tx_params.ibet_straight_bond import (
+ UpdateParams as IbetStraightBondUpdateParams,
+)
+from app.model.db import (
+ UTXO,
+ Account,
+ AccountRsaStatus,
+ IDXPersonalInfo,
+ Ledger,
+ LedgerDetailsData,
+ LedgerDetailsDataType,
+ LedgerDetailsTemplate,
+ LedgerTemplate,
+ Notification,
+ NotificationType,
+ Token,
+ TokenType,
+ TokenVersion,
+)
+from app.utils import ledger_utils
+from app.utils.contract_utils import ContractUtils
+from app.utils.e2ee_utils import E2EEUtils
+from config import TZ, WEB3_HTTP_PROVIDER, ZERO_ADDRESS
+from tests.account_config import config_eth_account
+
+web3 = Web3(Web3.HTTPProvider(WEB3_HTTP_PROVIDER))
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
+
+
+async def deploy_bond_token_contract(
+ issuer_address: str,
+ issuer_private_key: bytes,
+ personal_info_contract_address: str,
+ require_personal_info_registered: bool,
+):
+ arguments = [
+ "token.name",
+ "token.symbol",
+ 100,
+ 20,
+ "JPY",
+ "token.redemption_date",
+ 30,
+ "JPY",
+ "token.return_date",
+ "token.return_amount",
+ "token.purpose",
+ ]
+ bond_contrat = IbetStraightBondContract()
+ contract_address, _, _ = await bond_contrat.create(
+ arguments, issuer_address, issuer_private_key
+ )
+
+ data = IbetStraightBondUpdateParams()
+ data.personal_info_contract_address = personal_info_contract_address
+ data.require_personal_info_registered = require_personal_info_registered
+ await bond_contrat.update(data, issuer_address, issuer_private_key)
+
+ return contract_address
+
+
+async def deploy_share_token_contract(
+ issuer_address: str,
+ issuer_private_key: bytes,
+ personal_info_contract_address: str,
+ require_personal_info_registered: bool,
+):
+ arguments = [
+ "token.name",
+ "token.symbol",
+ 100,
+ 20,
+ 3,
+ "token.dividend_record_date",
+ "token.dividend_payment_date",
+ "token.cancellation_date",
+ 200,
+ ]
+ share_contract = IbetShareContract()
+ contract_address, _, _ = await share_contract.create(
+ arguments, issuer_address, issuer_private_key
+ )
+
+ data = IbetShareUpdateParams()
+ data.personal_info_contract_address = personal_info_contract_address
+ data.require_personal_info_registered = require_personal_info_registered
+ await share_contract.update(data, issuer_address, issuer_private_key)
+
+ return contract_address
+
+
+def deploy_personal_info_contract(address: str, private_key: bytes):
+ contract_address, _, _ = ContractUtils.deploy_contract(
+ "PersonalInfo", [], address, private_key
+ )
+ return contract_address
+
+
+async def register_personal_info(
+ contract_address: str, issuer_account: Account, investor_list: list
+):
+ personal_info = PersonalInfoContract(issuer_account, contract_address)
+ for investor in investor_list:
+ await personal_info.register_info(investor["address"], investor["data"])
+
+
+class TestCreateLedger:
+ ###########################################################################
+ # Normal Case
+ ###########################################################################
+
+ #
+ # Share Token
+ # require_personal_info_registered: True
+ # All personal information except issuer one has been registered
+ # -> "some_personal_info_not_registered" = False
+ @pytest.mark.asyncio
+ async def test_normal_1_1_1(self, db, async_db):
+ issuer = config_eth_account("user5")
+ issuer_address = issuer["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=issuer["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_1 = config_eth_account("user1")
+ user_address_1 = user_1["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_2 = user_2["address"]
+ user_private_key_2 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data: Issuer account settings
+ _account = Account()
+ _account.issuer_address = issuer_address
+ _account.keyfile = issuer["keyfile_json"]
+ _account.eoa_password = E2EEUtils.encrypt("password")
+ _account.rsa_private_key = issuer["rsa_private_key"]
+ _account.rsa_public_key = issuer["rsa_public_key"]
+ _account.rsa_passphrase = E2EEUtils.encrypt("password")
+ _account.rsa_status = AccountRsaStatus.SET.value
+ db.add(_account)
+
+ # Prepare data: Personal info contract
+ personal_info_contract_address = deploy_personal_info_contract(
+ issuer_address, issuer_private_key
+ )
+ await register_personal_info(
+ personal_info_contract_address,
+ _account,
+ [
+ {
+ "address": user_address_1,
+ "private_key": user_private_key_1,
+ "data": {
+ "name": "name_test_con_1",
+ "address": "address_test_con_1",
+ },
+ },
+ {
+ "address": user_address_2,
+ "private_key": user_private_key_2,
+ "data": {
+ "name": "name_test_con_2",
+ "address": "address_test_con_2",
+ },
+ },
+ ],
+ )
+
+ # Prepare data: IDXPersonalInfo
+ # - Only user_1
+ # - user_2 information is obtained from contract data
+ _idx_personal_info_1 = IDXPersonalInfo()
+ _idx_personal_info_1.account_address = user_address_1
+ _idx_personal_info_1.issuer_address = issuer_address
+ _idx_personal_info_1.personal_info = {
+ "name": "name_test_db_1",
+ "address": "address_test_db_1",
+ }
+ db.add(_idx_personal_info_1)
+
+ # Prepare data: Token
+ token_address_1 = await deploy_share_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract_address,
+ require_personal_info_registered=True,
+ )
+ _token_1 = Token()
+ _token_1.type = TokenType.IBET_SHARE.value
+ _token_1.tx_hash = ""
+ _token_1.issuer_address = issuer_address
+ _token_1.token_address = token_address_1
+ _token_1.abi = {}
+ _token_1.version = TokenVersion.V_24_06
+ db.add(_token_1)
+
+ # Prepare data: UTXO
+ # - user_1: "2022/01/01" = 100 + 10, "2022/01/02" = 30 + 40
+ # - user_2: "2022/01/01" = 200 + 20, "2022/01/02" = 40 + 2
+ # - issuer: "2022/01/01" = 300
+ _utxo_1 = UTXO()
+ _utxo_1.transaction_hash = "tx1"
+ _utxo_1.account_address = user_address_1
+ _utxo_1.token_address = token_address_1
+ _utxo_1.amount = 100
+ _utxo_1.block_number = 1
+ _utxo_1.block_timestamp = datetime.strptime(
+ "2021/12/31 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_1)
+
+ _utxo_2 = UTXO()
+ _utxo_2.transaction_hash = "tx2"
+ _utxo_2.account_address = user_address_1
+ _utxo_2.token_address = token_address_1
+ _utxo_2.amount = 10
+ _utxo_2.block_number = 2
+ _utxo_2.block_timestamp = datetime.strptime(
+ "2022/01/01 01:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_2)
+
+ _utxo_3 = UTXO()
+ _utxo_3.transaction_hash = "tx3"
+ _utxo_3.account_address = user_address_1
+ _utxo_3.token_address = token_address_1
+ _utxo_3.amount = 30
+ _utxo_3.block_number = 3
+ _utxo_3.block_timestamp = datetime.strptime(
+ "2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_utxo_3)
+
+ _utxo_4 = UTXO()
+ _utxo_4.transaction_hash = "tx4"
+ _utxo_4.account_address = user_address_1
+ _utxo_4.token_address = token_address_1
+ _utxo_4.amount = 40
+ _utxo_4.block_number = 4
+ _utxo_4.block_timestamp = datetime.strptime(
+ "2022/01/02 01:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_utxo_4)
+
+ _utxo_5 = UTXO()
+ _utxo_5.transaction_hash = "tx5"
+ _utxo_5.account_address = user_address_2
+ _utxo_5.token_address = token_address_1
+ _utxo_5.amount = 200
+ _utxo_5.block_number = 5
+ _utxo_5.block_timestamp = datetime.strptime(
+ "2021/12/31 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_5)
+
+ _utxo_6 = UTXO()
+ _utxo_6.transaction_hash = "tx6"
+ _utxo_6.account_address = user_address_2
+ _utxo_6.token_address = token_address_1
+ _utxo_6.amount = 20
+ _utxo_6.block_number = 6
+ _utxo_6.block_timestamp = datetime.strptime(
+ "2022/01/01 01:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_6)
+
+ _utxo_7 = UTXO()
+ _utxo_7.transaction_hash = "tx7"
+ _utxo_7.account_address = user_address_2
+ _utxo_7.token_address = token_address_1
+ _utxo_7.amount = 40
+ _utxo_7.block_number = 7
+ _utxo_7.block_timestamp = datetime.strptime(
+ "2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_utxo_7)
+
+ _utxo_8 = UTXO()
+ _utxo_8.transaction_hash = "tx8"
+ _utxo_8.account_address = user_address_2
+ _utxo_8.token_address = token_address_1
+ _utxo_8.amount = 2
+ _utxo_8.block_number = 8
+ _utxo_8.block_timestamp = datetime.strptime(
+ "2022/01/02 01:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_utxo_8)
+
+ _utxo_9 = UTXO()
+ _utxo_9.transaction_hash = "tx9"
+ _utxo_9.account_address = issuer_address
+ _utxo_9.token_address = token_address_1
+ _utxo_9.amount = 300
+ _utxo_9.block_number = 9
+ _utxo_9.block_timestamp = datetime.strptime(
+ "2021/12/31 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_9)
+
+ # Prepare data: Ledger template
+ _template = LedgerTemplate()
+ _template.token_address = token_address_1
+ _template.issuer_address = issuer_address
+ _template.headers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "テスト項目1": "テスト値1",
+ "テスト項目2": {
+ "テスト項目A": "テスト値2A",
+ "テスト項目B": "テスト値2B",
+ },
+ "テスト項目3": {
+ "テスト項目A": {"テスト項目a": "テスト値3Aa"},
+ "テスト項目B": "テスト値3B",
+ },
+ },
+ ]
+ _template.token_name = "受益権テスト"
+ _template.footers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "f-テスト項目1": "f-テスト値1",
+ "f-テスト項目2": {
+ "f-テスト項目A": "f-テスト値2A",
+ "f-テスト項目B": "f-テスト値2B",
+ },
+ "f-テスト項目3": {
+ "f-テスト項目A": {"f-テスト項目a": "f-テスト値3Aa"},
+ "f-テスト項目B": "f-テスト値3B",
+ },
+ },
+ ]
+ db.add(_template)
+
+ # Prepare data: Ledger template details 1
+ _details_1 = LedgerDetailsTemplate()
+ _details_1.token_address = token_address_1
+ _details_1.token_detail_type = "優先受益権"
+ _details_1.headers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test項目1": "test値1",
+ "test項目2": {
+ "test項目A": "test値2A",
+ },
+ },
+ ]
+ _details_1.footers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test-item1": "test-value1",
+ "test-item2": {"test-itemA": {"test-item": "test-value2Aa"}},
+ },
+ ]
+ _details_1.data_type = LedgerDetailsDataType.IBET_FIN.value
+ _details_1.data_source = token_address_1
+ db.add(_details_1)
+
+ # Prepare data: Ledger template details 2
+ _details_2 = LedgerDetailsTemplate()
+ _details_2.token_address = token_address_1
+ _details_2.token_detail_type = "劣後受益権"
+ _details_2.headers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "d-test項目1": "d-test値1",
+ "d-test項目2": "d-test値2",
+ },
+ ]
+ _details_2.footers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "f-d-test項目1": "d-test値1",
+ "f-d-test項目2": "d-test値2",
+ },
+ ]
+ _details_2.data_type = LedgerDetailsDataType.DB.value
+ _details_2.data_source = "data_id_2"
+ db.add(_details_2)
+
+ _details_2_data_1 = LedgerDetailsData()
+ _details_2_data_1.token_address = token_address_1
+ _details_2_data_1.data_id = "data_id_2"
+ _details_2_data_1.name = "test_data_name_1"
+ _details_2_data_1.address = "test_data_address_1"
+ _details_2_data_1.amount = 100
+ _details_2_data_1.price = 200
+ _details_2_data_1.balance = 20000
+ _details_2_data_1.acquisition_date = "2022/03/03"
+ db.add(_details_2_data_1)
+
+ _details_2_data_2 = LedgerDetailsData()
+ _details_2_data_2.token_address = token_address_1
+ _details_2_data_2.data_id = "data_id_2"
+ _details_2_data_2.name = "test_data_name_2"
+ _details_2_data_2.address = "test_data_address_2"
+ _details_2_data_2.amount = 30
+ _details_2_data_2.price = 40
+ _details_2_data_2.balance = 1200
+ _details_2_data_2.acquisition_date = "2022/12/03"
+ db.add(_details_2_data_2)
+
+ db.commit()
+
+ # Execute
+ await ledger_utils.create_ledger(token_address_1, async_db)
+ await async_db.commit()
+ await async_db.close()
+
+ # Assertion
+ _notifications = db.scalars(select(Notification)).all()
+ assert len(_notifications) == 1
+ _notification = db.scalars(select(Notification).limit(1)).first()
+ assert _notification.id == 1
+ assert _notification.notice_id is not None
+ assert _notification.issuer_address == issuer_address
+ assert _notification.priority == 0
+ assert _notification.type == NotificationType.CREATE_LEDGER_INFO
+ assert _notification.code == 0
+ assert _notification.metainfo == {
+ "token_address": token_address_1,
+ "token_type": TokenType.IBET_SHARE.value,
+ "ledger_id": 1,
+ }
+
+ _ledger = db.scalars(select(Ledger).limit(1)).first()
+ assert _ledger.id == 1
+ assert _ledger.token_address == token_address_1
+ assert _ledger.token_type == TokenType.IBET_SHARE.value
+ now_ymd = datetime.now(pytz.timezone(TZ)).strftime("%Y/%m/%d")
+ assert _ledger.ledger == {
+ "created": now_ymd,
+ "token_name": "受益権テスト",
+ "currency": "",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "テスト項目1": "テスト値1",
+ "テスト項目2": {
+ "テスト項目A": "テスト値2A",
+ "テスト項目B": "テスト値2B",
+ },
+ "テスト項目3": {
+ "テスト項目A": {"テスト項目a": "テスト値3Aa"},
+ "テスト項目B": "テスト値3B",
+ },
+ },
+ ],
+ "details": [
+ {
+ "token_detail_type": "優先受益権",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test項目1": "test値1",
+ "test項目2": {
+ "test項目A": "test値2A",
+ },
+ },
+ ],
+ "data": [
+ {
+ "account_address": issuer_address,
+ "name": None,
+ "address": None,
+ "amount": 300,
+ "price": 200,
+ "balance": 300 * 200,
+ "acquisition_date": "2022/01/01",
+ },
+ {
+ "account_address": user_address_2,
+ "name": "name_test_con_2",
+ "address": "address_test_con_2",
+ "amount": 220,
+ "price": 200,
+ "balance": 220 * 200,
+ "acquisition_date": "2022/01/01",
+ },
+ {
+ "account_address": user_address_2,
+ "name": "name_test_con_2",
+ "address": "address_test_con_2",
+ "amount": 42,
+ "price": 200,
+ "balance": 42 * 200,
+ "acquisition_date": "2022/01/02",
+ },
+ {
+ "account_address": user_address_1,
+ "name": "name_test_db_1",
+ "address": "address_test_db_1",
+ "amount": 110,
+ "price": 200,
+ "balance": 110 * 200,
+ "acquisition_date": "2022/01/01",
+ },
+ {
+ "account_address": user_address_1,
+ "name": "name_test_db_1",
+ "address": "address_test_db_1",
+ "amount": 70,
+ "price": 200,
+ "balance": 70 * 200,
+ "acquisition_date": "2022/01/02",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test-item1": "test-value1",
+ "test-item2": {
+ "test-itemA": {"test-item": "test-value2Aa"}
+ },
+ },
+ ],
+ "some_personal_info_not_registered": False,
+ },
+ {
+ "token_detail_type": "劣後受益権",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "d-test項目1": "d-test値1",
+ "d-test項目2": "d-test値2",
+ },
+ ],
+ "data": [
+ {
+ "account_address": None,
+ "name": "test_data_name_1",
+ "address": "test_data_address_1",
+ "amount": 100,
+ "price": 200,
+ "balance": 20000,
+ "acquisition_date": "2022/03/03",
+ },
+ {
+ "account_address": None,
+ "name": "test_data_name_2",
+ "address": "test_data_address_2",
+ "amount": 30,
+ "price": 40,
+ "balance": 1200,
+ "acquisition_date": "2022/12/03",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "f-d-test項目1": "d-test値1",
+ "f-d-test項目2": "d-test値2",
+ },
+ ],
+ "some_personal_info_not_registered": False,
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "f-テスト項目1": "f-テスト値1",
+ "f-テスト項目2": {
+ "f-テスト項目A": "f-テスト値2A",
+ "f-テスト項目B": "f-テスト値2B",
+ },
+ "f-テスト項目3": {
+ "f-テスト項目A": {"f-テスト項目a": "f-テスト値3Aa"},
+ "f-テスト項目B": "f-テスト値3B",
+ },
+ },
+ ],
+ }
+ db.close()
+
+ #
+ # Share Token
+ # require_personal_info_registered: True
+ # Some personal information except issuer one has not been registered
+ # -> "some_personal_info_not_registered" = True
+ @pytest.mark.asyncio
+ async def test_normal_1_1_2(self, db, async_db):
+ issuer = config_eth_account("user5")
+ issuer_address = issuer["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=issuer["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_1 = config_eth_account("user1")
+ user_address_1 = user_1["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_2 = user_2["address"]
+ user_private_key_2 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data: Issuer account settings
+ _account = Account()
+ _account.issuer_address = issuer_address
+ _account.keyfile = issuer["keyfile_json"]
+ _account.eoa_password = E2EEUtils.encrypt("password")
+ _account.rsa_private_key = issuer["rsa_private_key"]
+ _account.rsa_public_key = issuer["rsa_public_key"]
+ _account.rsa_passphrase = E2EEUtils.encrypt("password")
+ _account.rsa_status = AccountRsaStatus.SET.value
+ db.add(_account)
+
+ # Prepare data: Personal info contract
+ # - Only user_1 information is registered but the all field is null
+ personal_info_contract_address = deploy_personal_info_contract(
+ issuer_address, issuer_private_key
+ )
+ await register_personal_info(
+ personal_info_contract_address,
+ _account,
+ [
+ {
+ "address": user_address_1,
+ "private_key": user_private_key_1,
+ "data": {
+ "name": None,
+ "address": None,
+ },
+ },
+ ],
+ )
+
+ # There is no indexed personal info
+
+ # Prepare data: Token
+ token_address_1 = await deploy_share_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract_address,
+ require_personal_info_registered=True,
+ )
+ _token_1 = Token()
+ _token_1.type = TokenType.IBET_SHARE.value
+ _token_1.tx_hash = ""
+ _token_1.issuer_address = issuer_address
+ _token_1.token_address = token_address_1
+ _token_1.abi = {}
+ _token_1.version = TokenVersion.V_24_06
+ db.add(_token_1)
+
+ # Prepare data: UTXO
+ # - user_1: "2022/01/01" = 100 + 10, "2022/01/02" = 30 + 40
+ # - user_2: "2022/01/01" = 200 + 20, "2022/01/02" = 40 + 2
+ # - issuer: "2022/01/01" = 300
+ _utxo_1 = UTXO()
+ _utxo_1.transaction_hash = "tx1"
+ _utxo_1.account_address = user_address_1
+ _utxo_1.token_address = token_address_1
+ _utxo_1.amount = 100
+ _utxo_1.block_number = 1
+ _utxo_1.block_timestamp = datetime.strptime(
+ "2021/12/31 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_1)
+
+ _utxo_2 = UTXO()
+ _utxo_2.transaction_hash = "tx2"
+ _utxo_2.account_address = user_address_1
+ _utxo_2.token_address = token_address_1
+ _utxo_2.amount = 10
+ _utxo_2.block_number = 2
+ _utxo_2.block_timestamp = datetime.strptime(
+ "2022/01/01 01:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_2)
+
+ _utxo_3 = UTXO()
+ _utxo_3.transaction_hash = "tx3"
+ _utxo_3.account_address = user_address_1
+ _utxo_3.token_address = token_address_1
+ _utxo_3.amount = 30
+ _utxo_3.block_number = 3
+ _utxo_3.block_timestamp = datetime.strptime(
+ "2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_utxo_3)
+
+ _utxo_4 = UTXO()
+ _utxo_4.transaction_hash = "tx4"
+ _utxo_4.account_address = user_address_1
+ _utxo_4.token_address = token_address_1
+ _utxo_4.amount = 40
+ _utxo_4.block_number = 4
+ _utxo_4.block_timestamp = datetime.strptime(
+ "2022/01/02 01:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_utxo_4)
+
+ _utxo_5 = UTXO()
+ _utxo_5.transaction_hash = "tx5"
+ _utxo_5.account_address = user_address_2
+ _utxo_5.token_address = token_address_1
+ _utxo_5.amount = 200
+ _utxo_5.block_number = 5
+ _utxo_5.block_timestamp = datetime.strptime(
+ "2021/12/31 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_5)
+
+ _utxo_6 = UTXO()
+ _utxo_6.transaction_hash = "tx6"
+ _utxo_6.account_address = user_address_2
+ _utxo_6.token_address = token_address_1
+ _utxo_6.amount = 20
+ _utxo_6.block_number = 6
+ _utxo_6.block_timestamp = datetime.strptime(
+ "2022/01/01 01:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_6)
+
+ _utxo_7 = UTXO()
+ _utxo_7.transaction_hash = "tx7"
+ _utxo_7.account_address = user_address_2
+ _utxo_7.token_address = token_address_1
+ _utxo_7.amount = 40
+ _utxo_7.block_number = 7
+ _utxo_7.block_timestamp = datetime.strptime(
+ "2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_utxo_7)
+
+ _utxo_8 = UTXO()
+ _utxo_8.transaction_hash = "tx8"
+ _utxo_8.account_address = user_address_2
+ _utxo_8.token_address = token_address_1
+ _utxo_8.amount = 2
+ _utxo_8.block_number = 8
+ _utxo_8.block_timestamp = datetime.strptime(
+ "2022/01/02 01:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_utxo_8)
+
+ _utxo_9 = UTXO()
+ _utxo_9.transaction_hash = "tx9"
+ _utxo_9.account_address = issuer_address
+ _utxo_9.token_address = token_address_1
+ _utxo_9.amount = 300
+ _utxo_9.block_number = 9
+ _utxo_9.block_timestamp = datetime.strptime(
+ "2021/12/31 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_9)
+
+ # Prepare data: Ledger template
+ _template = LedgerTemplate()
+ _template.token_address = token_address_1
+ _template.issuer_address = issuer_address
+ _template.headers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "テスト項目1": "テスト値1",
+ "テスト項目2": {
+ "テスト項目A": "テスト値2A",
+ "テスト項目B": "テスト値2B",
+ },
+ "テスト項目3": {
+ "テスト項目A": {"テスト項目a": "テスト値3Aa"},
+ "テスト項目B": "テスト値3B",
+ },
+ },
+ ]
+ _template.token_name = "受益権テスト"
+ _template.footers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "f-テスト項目1": "f-テスト値1",
+ "f-テスト項目2": {
+ "f-テスト項目A": "f-テスト値2A",
+ "f-テスト項目B": "f-テスト値2B",
+ },
+ "f-テスト項目3": {
+ "f-テスト項目A": {"f-テスト項目a": "f-テスト値3Aa"},
+ "f-テスト項目B": "f-テスト値3B",
+ },
+ },
+ ]
+ db.add(_template)
+
+ # Prepare data: Ledger template details 1
+ _details_1 = LedgerDetailsTemplate()
+ _details_1.token_address = token_address_1
+ _details_1.token_detail_type = "優先受益権"
+ _details_1.headers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test項目1": "test値1",
+ "test項目2": {
+ "test項目A": "test値2A",
+ },
+ },
+ ]
+ _details_1.footers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test-item1": "test-value1",
+ "test-item2": {"test-itemA": {"test-item": "test-value2Aa"}},
+ },
+ ]
+ _details_1.data_type = LedgerDetailsDataType.IBET_FIN.value
+ _details_1.data_source = token_address_1
+ db.add(_details_1)
+
+ # Prepare data: Ledger template details 2
+ _details_2 = LedgerDetailsTemplate()
+ _details_2.token_address = token_address_1
+ _details_2.token_detail_type = "劣後受益権"
+ _details_2.headers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "d-test項目1": "d-test値1",
+ "d-test項目2": "d-test値2",
+ },
+ ]
+ _details_2.footers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "f-d-test項目1": "d-test値1",
+ "f-d-test項目2": "d-test値2",
+ },
+ ]
+ _details_2.data_type = LedgerDetailsDataType.DB.value
+ _details_2.data_source = "data_id_2"
+ db.add(_details_2)
+
+ _details_2_data_1 = LedgerDetailsData()
+ _details_2_data_1.token_address = token_address_1
+ _details_2_data_1.data_id = "data_id_2"
+ _details_2_data_1.name = "test_data_name_1"
+ _details_2_data_1.address = "test_data_address_1"
+ _details_2_data_1.amount = 100
+ _details_2_data_1.price = 200
+ _details_2_data_1.balance = 20000
+ _details_2_data_1.acquisition_date = "2022/03/03"
+ db.add(_details_2_data_1)
+
+ _details_2_data_2 = LedgerDetailsData()
+ _details_2_data_2.token_address = token_address_1
+ _details_2_data_2.data_id = "data_id_2"
+ _details_2_data_2.name = "test_data_name_2"
+ _details_2_data_2.address = "test_data_address_2"
+ _details_2_data_2.amount = 30
+ _details_2_data_2.price = 40
+ _details_2_data_2.balance = 1200
+ _details_2_data_2.acquisition_date = "2022/12/03"
+ db.add(_details_2_data_2)
+
+ db.commit()
+
+ # Execute
+ await ledger_utils.create_ledger(token_address_1, async_db)
+ await async_db.commit()
+ await async_db.close()
+
+ # Assertion
+ _notifications = db.scalars(select(Notification)).all()
+ assert len(_notifications) == 1
+ _notification = db.scalars(select(Notification).limit(1)).first()
+ assert _notification.id == 1
+ assert _notification.notice_id is not None
+ assert _notification.issuer_address == issuer_address
+ assert _notification.priority == 0
+ assert _notification.type == NotificationType.CREATE_LEDGER_INFO
+ assert _notification.code == 0
+ assert _notification.metainfo == {
+ "token_address": token_address_1,
+ "token_type": TokenType.IBET_SHARE.value,
+ "ledger_id": 1,
+ }
+
+ _ledger = db.scalars(select(Ledger).limit(1)).first()
+ assert _ledger.id == 1
+ assert _ledger.token_address == token_address_1
+ assert _ledger.token_type == TokenType.IBET_SHARE.value
+ now_ymd = datetime.now(pytz.timezone(TZ)).strftime("%Y/%m/%d")
+ assert _ledger.ledger == {
+ "created": now_ymd,
+ "token_name": "受益権テスト",
+ "currency": "",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "テスト項目1": "テスト値1",
+ "テスト項目2": {
+ "テスト項目A": "テスト値2A",
+ "テスト項目B": "テスト値2B",
+ },
+ "テスト項目3": {
+ "テスト項目A": {"テスト項目a": "テスト値3Aa"},
+ "テスト項目B": "テスト値3B",
+ },
+ },
+ ],
+ "details": [
+ {
+ "token_detail_type": "優先受益権",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test項目1": "test値1",
+ "test項目2": {
+ "test項目A": "test値2A",
+ },
+ },
+ ],
+ "data": [
+ {
+ "account_address": issuer_address,
+ "name": None,
+ "address": None,
+ "amount": 300,
+ "price": 200,
+ "balance": 300 * 200,
+ "acquisition_date": "2022/01/01",
+ },
+ {
+ "account_address": user_address_2,
+ "name": None,
+ "address": None,
+ "amount": 220,
+ "price": 200,
+ "balance": 220 * 200,
+ "acquisition_date": "2022/01/01",
+ },
+ {
+ "account_address": user_address_2,
+ "name": None,
+ "address": None,
+ "amount": 42,
+ "price": 200,
+ "balance": 42 * 200,
+ "acquisition_date": "2022/01/02",
+ },
+ {
+ "account_address": user_address_1,
+ "name": None,
+ "address": None,
+ "amount": 110,
+ "price": 200,
+ "balance": 110 * 200,
+ "acquisition_date": "2022/01/01",
+ },
+ {
+ "account_address": user_address_1,
+ "name": None,
+ "address": None,
+ "amount": 70,
+ "price": 200,
+ "balance": 70 * 200,
+ "acquisition_date": "2022/01/02",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test-item1": "test-value1",
+ "test-item2": {
+ "test-itemA": {"test-item": "test-value2Aa"}
+ },
+ },
+ ],
+ "some_personal_info_not_registered": True,
+ },
+ {
+ "token_detail_type": "劣後受益権",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "d-test項目1": "d-test値1",
+ "d-test項目2": "d-test値2",
+ },
+ ],
+ "data": [
+ {
+ "account_address": None,
+ "name": "test_data_name_1",
+ "address": "test_data_address_1",
+ "amount": 100,
+ "price": 200,
+ "balance": 20000,
+ "acquisition_date": "2022/03/03",
+ },
+ {
+ "account_address": None,
+ "name": "test_data_name_2",
+ "address": "test_data_address_2",
+ "amount": 30,
+ "price": 40,
+ "balance": 1200,
+ "acquisition_date": "2022/12/03",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "f-d-test項目1": "d-test値1",
+ "f-d-test項目2": "d-test値2",
+ },
+ ],
+ "some_personal_info_not_registered": False,
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "f-テスト項目1": "f-テスト値1",
+ "f-テスト項目2": {
+ "f-テスト項目A": "f-テスト値2A",
+ "f-テスト項目B": "f-テスト値2B",
+ },
+ "f-テスト項目3": {
+ "f-テスト項目A": {"f-テスト項目a": "f-テスト値3Aa"},
+ "f-テスト項目B": "f-テスト値3B",
+ },
+ },
+ ],
+ }
+ db.close()
+
+ #
+ # Share Token
+ # require_personal_info_registered: False
+ # - Perform searches only on indexed personal information.
+ # - Even if personal information exists in the contract, it will not be referenced.
+ # No personal information indexed
+ # -> "some_personal_info_not_registered" = True
+ @pytest.mark.asyncio
+ async def test_normal_1_2(self, db, async_db):
+ issuer = config_eth_account("user5")
+ issuer_address = issuer["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=issuer["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_1 = config_eth_account("user1")
+ user_address_1 = user_1["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data: Issuer account settings
+ _account = Account()
+ _account.issuer_address = issuer_address
+ _account.keyfile = issuer["keyfile_json"]
+ _account.eoa_password = E2EEUtils.encrypt("password")
+ _account.rsa_private_key = issuer["rsa_private_key"]
+ _account.rsa_public_key = issuer["rsa_public_key"]
+ _account.rsa_passphrase = E2EEUtils.encrypt("password")
+ _account.rsa_status = AccountRsaStatus.SET.value
+ db.add(_account)
+
+ # Prepare data: Personal info contract
+ # - Registered data is not referenced
+ personal_info_contract_address = deploy_personal_info_contract(
+ issuer_address, issuer_private_key
+ )
+ await register_personal_info(
+ personal_info_contract_address,
+ _account,
+ [
+ {
+ "address": user_address_1,
+ "private_key": user_private_key_1,
+ "data": {
+ "name": "name_test_con_1",
+ "address": "address_test_con_1",
+ },
+ },
+ ],
+ )
+
+ # Prepare data: Token
+ token_address_1 = await deploy_share_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract_address,
+ require_personal_info_registered=False,
+ )
+ _token_1 = Token()
+ _token_1.type = TokenType.IBET_SHARE.value
+ _token_1.tx_hash = ""
+ _token_1.issuer_address = issuer_address
+ _token_1.token_address = token_address_1
+ _token_1.abi = {}
+ _token_1.version = TokenVersion.V_24_06
+ db.add(_token_1)
+
+ # Prepare data: UTXO
+ # - user_1: "2022/01/01" = 100 + 10, "2022/01/02" = 30 + 40
+ _utxo_1 = UTXO()
+ _utxo_1.transaction_hash = "tx1"
+ _utxo_1.account_address = user_address_1
+ _utxo_1.token_address = token_address_1
+ _utxo_1.amount = 100
+ _utxo_1.block_number = 1
+ _utxo_1.block_timestamp = datetime.strptime(
+ "2021/12/31 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_1)
+
+ _utxo_2 = UTXO()
+ _utxo_2.transaction_hash = "tx2"
+ _utxo_2.account_address = user_address_1
+ _utxo_2.token_address = token_address_1
+ _utxo_2.amount = 10
+ _utxo_2.block_number = 2
+ _utxo_2.block_timestamp = datetime.strptime(
+ "2022/01/01 01:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_2)
+
+ _utxo_3 = UTXO()
+ _utxo_3.transaction_hash = "tx3"
+ _utxo_3.account_address = user_address_1
+ _utxo_3.token_address = token_address_1
+ _utxo_3.amount = 30
+ _utxo_3.block_number = 3
+ _utxo_3.block_timestamp = datetime.strptime(
+ "2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_utxo_3)
+
+ _utxo_4 = UTXO()
+ _utxo_4.transaction_hash = "tx4"
+ _utxo_4.account_address = user_address_1
+ _utxo_4.token_address = token_address_1
+ _utxo_4.amount = 40
+ _utxo_4.block_number = 4
+ _utxo_4.block_timestamp = datetime.strptime(
+ "2022/01/02 01:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_utxo_4)
+
+ # Prepare data: Ledger template
+ _template = LedgerTemplate()
+ _template.token_address = token_address_1
+ _template.issuer_address = issuer_address
+ _template.headers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "テスト項目1": "テスト値1",
+ "テスト項目2": {
+ "テスト項目A": "テスト値2A",
+ "テスト項目B": "テスト値2B",
+ },
+ "テスト項目3": {
+ "テスト項目A": {"テスト項目a": "テスト値3Aa"},
+ "テスト項目B": "テスト値3B",
+ },
+ },
+ ]
+ _template.token_name = "受益権テスト"
+ _template.footers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "f-テスト項目1": "f-テスト値1",
+ "f-テスト項目2": {
+ "f-テスト項目A": "f-テスト値2A",
+ "f-テスト項目B": "f-テスト値2B",
+ },
+ "f-テスト項目3": {
+ "f-テスト項目A": {"f-テスト項目a": "f-テスト値3Aa"},
+ "f-テスト項目B": "f-テスト値3B",
+ },
+ },
+ ]
+ db.add(_template)
+
+ # Prepare data: Ledger template details 1
+ _details_1 = LedgerDetailsTemplate()
+ _details_1.token_address = token_address_1
+ _details_1.token_detail_type = "優先受益権"
+ _details_1.headers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test項目1": "test値1",
+ "test項目2": {
+ "test項目A": "test値2A",
+ },
+ },
+ ]
+ _details_1.footers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test-item1": "test-value1",
+ "test-item2": {"test-itemA": {"test-item": "test-value2Aa"}},
+ },
+ ]
+ _details_1.data_type = LedgerDetailsDataType.IBET_FIN.value
+ _details_1.data_source = token_address_1
+ db.add(_details_1)
+
+ db.commit()
+
+ # Execute
+ await ledger_utils.create_ledger(token_address_1, async_db)
+ await async_db.commit()
+ await async_db.close()
+
+ # Assertion
+ _notifications = db.scalars(select(Notification)).all()
+ assert len(_notifications) == 1
+
+ _notification = db.scalars(select(Notification).limit(1)).first()
+ assert _notification.id == 1
+ assert _notification.notice_id is not None
+ assert _notification.issuer_address == issuer_address
+ assert _notification.priority == 0
+ assert _notification.type == NotificationType.CREATE_LEDGER_INFO
+ assert _notification.code == 0
+ assert _notification.metainfo == {
+ "token_address": token_address_1,
+ "token_type": TokenType.IBET_SHARE.value,
+ "ledger_id": 1,
+ }
+
+ _ledger = db.scalars(select(Ledger).limit(1)).first()
+ assert _ledger.id == 1
+ assert _ledger.token_address == token_address_1
+ assert _ledger.token_type == TokenType.IBET_SHARE.value
+ now_ymd = datetime.now(pytz.timezone(TZ)).strftime("%Y/%m/%d")
+ assert _ledger.ledger == {
+ "created": now_ymd,
+ "token_name": "受益権テスト",
+ "currency": "",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "テスト項目1": "テスト値1",
+ "テスト項目2": {
+ "テスト項目A": "テスト値2A",
+ "テスト項目B": "テスト値2B",
+ },
+ "テスト項目3": {
+ "テスト項目A": {"テスト項目a": "テスト値3Aa"},
+ "テスト項目B": "テスト値3B",
+ },
+ },
+ ],
+ "details": [
+ {
+ "token_detail_type": "優先受益権",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test項目1": "test値1",
+ "test項目2": {
+ "test項目A": "test値2A",
+ },
+ },
+ ],
+ "data": [
+ {
+ "account_address": user_address_1,
+ "name": None, # Not set
+ "address": None, # Not set
+ "amount": 110,
+ "price": 200,
+ "balance": 110 * 200,
+ "acquisition_date": "2022/01/01",
+ },
+ {
+ "account_address": user_address_1,
+ "name": None, # Not set
+ "address": None, # Not set
+ "amount": 70,
+ "price": 200,
+ "balance": 70 * 200,
+ "acquisition_date": "2022/01/02",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test-item1": "test-value1",
+ "test-item2": {
+ "test-itemA": {"test-item": "test-value2Aa"}
+ },
+ },
+ ],
+ "some_personal_info_not_registered": True,
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "f-テスト項目1": "f-テスト値1",
+ "f-テスト項目2": {
+ "f-テスト項目A": "f-テスト値2A",
+ "f-テスト項目B": "f-テスト値2B",
+ },
+ "f-テスト項目3": {
+ "f-テスト項目A": {"f-テスト項目a": "f-テスト値3Aa"},
+ "f-テスト項目B": "f-テスト値3B",
+ },
+ },
+ ],
+ }
+ db.close()
+
+ #
+ # Bond Token
+ # require_personal_info_registered: True
+ # All personal information except issuer one has been registered
+ # -> "some_personal_info_not_registered" = False
+ @pytest.mark.asyncio
+ async def test_normal_2_1_1(self, db, async_db):
+ issuer = config_eth_account("user5")
+ issuer_address = issuer["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=issuer["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_1 = config_eth_account("user1")
+ user_address_1 = user_1["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_2 = user_2["address"]
+ user_private_key_2 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data: Issuer account settings
+ _account = Account()
+ _account.issuer_address = issuer_address
+ _account.keyfile = issuer["keyfile_json"]
+ _account.eoa_password = E2EEUtils.encrypt("password")
+ _account.rsa_private_key = issuer["rsa_private_key"]
+ _account.rsa_public_key = issuer["rsa_public_key"]
+ _account.rsa_passphrase = E2EEUtils.encrypt("password")
+ _account.rsa_status = AccountRsaStatus.SET.value
+ db.add(_account)
+
+ # Prepare data: Personal info contract
+ personal_info_contract_address = deploy_personal_info_contract(
+ issuer_address, issuer_private_key
+ )
+ await register_personal_info(
+ personal_info_contract_address,
+ _account,
+ [
+ {
+ "address": user_address_1,
+ "private_key": user_private_key_1,
+ "data": {
+ "name": "name_test_con_1",
+ "address": "address_test_con_1",
+ },
+ },
+ {
+ "address": user_address_2,
+ "private_key": user_private_key_2,
+ "data": {
+ "name": "name_test_con_2",
+ "address": "address_test_con_2",
+ },
+ },
+ ],
+ )
+
+ # Prepare data: IDXPersonalInfo
+ # - Only user_1
+ # - user_2 information is obtained from contract data
+ _idx_personal_info_1 = IDXPersonalInfo()
+ _idx_personal_info_1.account_address = user_address_1
+ _idx_personal_info_1.issuer_address = issuer_address
+ _idx_personal_info_1.personal_info = {
+ "name": "name_test_db_1",
+ "address": "address_test_db_1",
+ }
+ db.add(_idx_personal_info_1)
+
+ # Prepare data: Token
+ token_address_1 = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract_address,
+ require_personal_info_registered=True,
+ )
+ _token_1 = Token()
+ _token_1.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token_1.tx_hash = ""
+ _token_1.issuer_address = issuer_address
+ _token_1.token_address = token_address_1
+ _token_1.abi = {}
+ _token_1.version = TokenVersion.V_24_06
+ db.add(_token_1)
+
+ # Prepare data: UTXO
+ # - user_1: "2022/01/01" = 100 + 10, "2022/01/02" = 30 + 40
+ # - user_2: "2022/01/01" = 200 + 20, "2022/01/02" = 40 + 2
+ _utxo_1 = UTXO()
+ _utxo_1.transaction_hash = "tx1"
+ _utxo_1.account_address = user_address_1
+ _utxo_1.token_address = token_address_1
+ _utxo_1.amount = 100
+ _utxo_1.block_number = 1
+ _utxo_1.block_timestamp = datetime.strptime(
+ "2021/12/31 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_1)
+
+ _utxo_2 = UTXO()
+ _utxo_2.transaction_hash = "tx2"
+ _utxo_2.account_address = user_address_1
+ _utxo_2.token_address = token_address_1
+ _utxo_2.amount = 10
+ _utxo_2.block_number = 2
+ _utxo_2.block_timestamp = datetime.strptime(
+ "2022/01/01 01:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_2)
+
+ _utxo_3 = UTXO()
+ _utxo_3.transaction_hash = "tx3"
+ _utxo_3.account_address = user_address_1
+ _utxo_3.token_address = token_address_1
+ _utxo_3.amount = 30
+ _utxo_3.block_number = 3
+ _utxo_3.block_timestamp = datetime.strptime(
+ "2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_utxo_3)
+
+ _utxo_4 = UTXO()
+ _utxo_4.transaction_hash = "tx4"
+ _utxo_4.account_address = user_address_1
+ _utxo_4.token_address = token_address_1
+ _utxo_4.amount = 40
+ _utxo_4.block_number = 4
+ _utxo_4.block_timestamp = datetime.strptime(
+ "2022/01/02 01:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_utxo_4)
+
+ _utxo_5 = UTXO()
+ _utxo_5.transaction_hash = "tx5"
+ _utxo_5.account_address = user_address_2
+ _utxo_5.token_address = token_address_1
+ _utxo_5.amount = 200
+ _utxo_5.block_number = 5
+ _utxo_5.block_timestamp = datetime.strptime(
+ "2021/12/31 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_5)
+
+ _utxo_6 = UTXO()
+ _utxo_6.transaction_hash = "tx6"
+ _utxo_6.account_address = user_address_2
+ _utxo_6.token_address = token_address_1
+ _utxo_6.amount = 20
+ _utxo_6.block_number = 6
+ _utxo_6.block_timestamp = datetime.strptime(
+ "2022/01/01 01:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_6)
+
+ _utxo_7 = UTXO()
+ _utxo_7.transaction_hash = "tx7"
+ _utxo_7.account_address = user_address_2
+ _utxo_7.token_address = token_address_1
+ _utxo_7.amount = 40
+ _utxo_7.block_number = 7
+ _utxo_7.block_timestamp = datetime.strptime(
+ "2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_utxo_7)
+
+ _utxo_8 = UTXO()
+ _utxo_8.transaction_hash = "tx8"
+ _utxo_8.account_address = user_address_2
+ _utxo_8.token_address = token_address_1
+ _utxo_8.amount = 2
+ _utxo_8.block_number = 8
+ _utxo_8.block_timestamp = datetime.strptime(
+ "2022/01/02 01:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_utxo_8)
+
+ _utxo_9 = UTXO()
+ _utxo_9.transaction_hash = "tx9"
+ _utxo_9.account_address = issuer_address
+ _utxo_9.token_address = token_address_1
+ _utxo_9.amount = 300
+ _utxo_9.block_number = 9
+ _utxo_9.block_timestamp = datetime.strptime(
+ "2021/12/31 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_9)
+
+ # Prepare data: Ledger template
+ _template = LedgerTemplate()
+ _template.token_address = token_address_1
+ _template.issuer_address = issuer_address
+ _template.token_name = "受益権テスト"
+ _template.headers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "テスト項目1": "テスト値1",
+ "テスト項目2": {
+ "テスト項目A": "テスト値2A",
+ "テスト項目B": "テスト値2B",
+ },
+ "テスト項目3": {
+ "テスト項目A": {"テスト項目a": "テスト値3Aa"},
+ "テスト項目B": "テスト値3B",
+ },
+ },
+ ]
+ _template.footers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "f-テスト項目1": "f-テスト値1",
+ "f-テスト項目2": {
+ "f-テスト項目A": "f-テスト値2A",
+ "f-テスト項目B": "f-テスト値2B",
+ },
+ "f-テスト項目3": {
+ "f-テスト項目A": {"f-テスト項目a": "f-テスト値3Aa"},
+ "f-テスト項目B": "f-テスト値3B",
+ },
+ },
+ ]
+ db.add(_template)
+
+ # Prepare data: Ledger template details 1
+ _details_1 = LedgerDetailsTemplate()
+ _details_1.token_address = token_address_1
+ _details_1.token_detail_type = "優先受益権"
+ _details_1.headers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test項目1": "test値1",
+ "test項目2": {
+ "test項目A": "test値2A",
+ },
+ },
+ ]
+ _details_1.footers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test-item1": "test-value1",
+ "test-item2": {"test-itemA": {"test-item": "test-value2Aa"}},
+ },
+ ]
+ _details_1.data_type = LedgerDetailsDataType.IBET_FIN.value
+ _details_1.data_source = token_address_1
+ db.add(_details_1)
+
+ # Prepare data: Ledger template details 2
+ _details_2 = LedgerDetailsTemplate()
+ _details_2.token_address = token_address_1
+ _details_2.token_detail_type = "劣後受益権"
+ _details_2.headers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "d-test項目1": "d-test値1",
+ "d-test項目2": "d-test値2",
+ },
+ ]
+ _details_2.footers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "f-d-test項目1": "d-test値1",
+ "f-d-test項目2": "d-test値2",
+ },
+ ]
+ _details_2.data_type = LedgerDetailsDataType.DB.value
+ _details_2.data_source = "data_id_2"
+ db.add(_details_2)
+
+ _details_2_data_1 = LedgerDetailsData()
+ _details_2_data_1.token_address = token_address_1
+ _details_2_data_1.data_id = "data_id_2"
+ _details_2_data_1.name = "test_data_name_1"
+ _details_2_data_1.address = "test_data_address_1"
+ _details_2_data_1.amount = 100
+ _details_2_data_1.price = 200
+ _details_2_data_1.balance = 20000
+ _details_2_data_1.acquisition_date = "2022/03/03"
+ db.add(_details_2_data_1)
+
+ _details_2_data_2 = LedgerDetailsData()
+ _details_2_data_2.token_address = token_address_1
+ _details_2_data_2.data_id = "data_id_2"
+ _details_2_data_2.name = "test_data_name_2"
+ _details_2_data_2.address = "test_data_address_2"
+ _details_2_data_2.amount = 30
+ _details_2_data_2.price = 40
+ _details_2_data_2.balance = 1200
+ _details_2_data_2.acquisition_date = "2022/12/03"
+ db.add(_details_2_data_2)
+
+ db.commit()
+
+ # Execute
+ await ledger_utils.create_ledger(token_address_1, async_db)
+ await async_db.commit()
+ await async_db.close()
+
+ # Assertion
+ _notifications = db.scalars(select(Notification)).all()
+ assert len(_notifications) == 1
+ _notification = db.scalars(select(Notification).limit(1)).first()
+ assert _notification.id == 1
+ assert _notification.notice_id is not None
+ assert _notification.issuer_address == issuer_address
+ assert _notification.priority == 0
+ assert _notification.type == NotificationType.CREATE_LEDGER_INFO
+ assert _notification.code == 0
+ assert _notification.metainfo == {
+ "token_address": token_address_1,
+ "token_type": TokenType.IBET_STRAIGHT_BOND.value,
+ "ledger_id": 1,
+ }
+ _ledger = db.scalars(select(Ledger).limit(1)).first()
+ assert _ledger.id == 1
+ assert _ledger.token_address == token_address_1
+ assert _ledger.token_type == TokenType.IBET_STRAIGHT_BOND.value
+ now_ymd = datetime.now(pytz.timezone(TZ)).strftime("%Y/%m/%d")
+ assert _ledger.ledger == {
+ "created": now_ymd,
+ "token_name": "受益権テスト",
+ "currency": "JPY",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "テスト項目1": "テスト値1",
+ "テスト項目2": {
+ "テスト項目A": "テスト値2A",
+ "テスト項目B": "テスト値2B",
+ },
+ "テスト項目3": {
+ "テスト項目A": {"テスト項目a": "テスト値3Aa"},
+ "テスト項目B": "テスト値3B",
+ },
+ },
+ ],
+ "details": [
+ {
+ "token_detail_type": "優先受益権",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test項目1": "test値1",
+ "test項目2": {
+ "test項目A": "test値2A",
+ },
+ },
+ ],
+ "data": [
+ {
+ "account_address": issuer_address,
+ "name": None,
+ "address": None,
+ "amount": 300,
+ "price": 20,
+ "balance": 300 * 20,
+ "acquisition_date": "2022/01/01",
+ },
+ {
+ "account_address": user_address_2,
+ "name": "name_test_con_2",
+ "address": "address_test_con_2",
+ "amount": 220,
+ "price": 20,
+ "balance": 220 * 20,
+ "acquisition_date": "2022/01/01",
+ },
+ {
+ "account_address": user_address_2,
+ "name": "name_test_con_2",
+ "address": "address_test_con_2",
+ "amount": 42,
+ "price": 20,
+ "balance": 42 * 20,
+ "acquisition_date": "2022/01/02",
+ },
+ {
+ "account_address": user_address_1,
+ "name": "name_test_db_1",
+ "address": "address_test_db_1",
+ "amount": 110,
+ "price": 20,
+ "balance": 110 * 20,
+ "acquisition_date": "2022/01/01",
+ },
+ {
+ "account_address": user_address_1,
+ "name": "name_test_db_1",
+ "address": "address_test_db_1",
+ "amount": 70,
+ "price": 20,
+ "balance": 70 * 20,
+ "acquisition_date": "2022/01/02",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test-item1": "test-value1",
+ "test-item2": {
+ "test-itemA": {"test-item": "test-value2Aa"}
+ },
+ },
+ ],
+ "some_personal_info_not_registered": False,
+ },
+ {
+ "token_detail_type": "劣後受益権",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "d-test項目1": "d-test値1",
+ "d-test項目2": "d-test値2",
+ },
+ ],
+ "data": [
+ {
+ "account_address": None,
+ "name": "test_data_name_1",
+ "address": "test_data_address_1",
+ "amount": 100,
+ "price": 200,
+ "balance": 20000,
+ "acquisition_date": "2022/03/03",
+ },
+ {
+ "account_address": None,
+ "name": "test_data_name_2",
+ "address": "test_data_address_2",
+ "amount": 30,
+ "price": 40,
+ "balance": 1200,
+ "acquisition_date": "2022/12/03",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "f-d-test項目1": "d-test値1",
+ "f-d-test項目2": "d-test値2",
+ },
+ ],
+ "some_personal_info_not_registered": False,
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "f-テスト項目1": "f-テスト値1",
+ "f-テスト項目2": {
+ "f-テスト項目A": "f-テスト値2A",
+ "f-テスト項目B": "f-テスト値2B",
+ },
+ "f-テスト項目3": {
+ "f-テスト項目A": {"f-テスト項目a": "f-テスト値3Aa"},
+ "f-テスト項目B": "f-テスト値3B",
+ },
+ },
+ ],
+ }
+ db.close()
+
+ #
+ # Bond Token
+ # require_personal_info_registered: True
+ # Some personal information except issuer one has not been registered
+ # -> "some_personal_info_not_registered" = True
+ @pytest.mark.asyncio
+ async def test_normal_2_1_2(self, db, async_db):
+ issuer = config_eth_account("user5")
+ issuer_address = issuer["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=issuer["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_1 = config_eth_account("user1")
+ user_address_1 = user_1["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_2 = user_2["address"]
+ user_private_key_2 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data: Issuer account settings
+ _account = Account()
+ _account.issuer_address = issuer_address
+ _account.keyfile = issuer["keyfile_json"]
+ _account.eoa_password = E2EEUtils.encrypt("password")
+ _account.rsa_private_key = issuer["rsa_private_key"]
+ _account.rsa_public_key = issuer["rsa_public_key"]
+ _account.rsa_passphrase = E2EEUtils.encrypt("password")
+ _account.rsa_status = AccountRsaStatus.SET.value
+ db.add(_account)
+
+ # Prepare data: Personal info contract
+ # - Only user_1 information is registered but the all field is null
+ personal_info_contract_address = deploy_personal_info_contract(
+ issuer_address, issuer_private_key
+ )
+ await register_personal_info(
+ personal_info_contract_address,
+ _account,
+ [
+ {
+ "address": user_address_1,
+ "private_key": user_private_key_1,
+ "data": {
+ "name": None,
+ "address": None,
+ },
+ },
+ ],
+ )
+
+ # There is no indexed personal info
+
+ # Prepare data: Token
+ token_address_1 = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract_address,
+ require_personal_info_registered=True,
+ )
+ _token_1 = Token()
+ _token_1.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token_1.tx_hash = ""
+ _token_1.issuer_address = issuer_address
+ _token_1.token_address = token_address_1
+ _token_1.abi = {}
+ _token_1.version = TokenVersion.V_24_06
+ db.add(_token_1)
+
+ # Prepare data: UTXO
+ # - user_1: "2022/01/01" = 100 + 10, "2022/01/02" = 30 + 40
+ # - user_2: "2022/01/01" = 200 + 20, "2022/01/02" = 40 + 2
+ _utxo_1 = UTXO()
+ _utxo_1.transaction_hash = "tx1"
+ _utxo_1.account_address = user_address_1
+ _utxo_1.token_address = token_address_1
+ _utxo_1.amount = 100
+ _utxo_1.block_number = 1
+ _utxo_1.block_timestamp = datetime.strptime(
+ "2021/12/31 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_1)
+
+ _utxo_2 = UTXO()
+ _utxo_2.transaction_hash = "tx2"
+ _utxo_2.account_address = user_address_1
+ _utxo_2.token_address = token_address_1
+ _utxo_2.amount = 10
+ _utxo_2.block_number = 2
+ _utxo_2.block_timestamp = datetime.strptime(
+ "2022/01/01 01:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_2)
+
+ _utxo_3 = UTXO()
+ _utxo_3.transaction_hash = "tx3"
+ _utxo_3.account_address = user_address_1
+ _utxo_3.token_address = token_address_1
+ _utxo_3.amount = 30
+ _utxo_3.block_number = 3
+ _utxo_3.block_timestamp = datetime.strptime(
+ "2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_utxo_3)
+
+ _utxo_4 = UTXO()
+ _utxo_4.transaction_hash = "tx4"
+ _utxo_4.account_address = user_address_1
+ _utxo_4.token_address = token_address_1
+ _utxo_4.amount = 40
+ _utxo_4.block_number = 4
+ _utxo_4.block_timestamp = datetime.strptime(
+ "2022/01/02 01:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_utxo_4)
+
+ _utxo_5 = UTXO()
+ _utxo_5.transaction_hash = "tx5"
+ _utxo_5.account_address = user_address_2
+ _utxo_5.token_address = token_address_1
+ _utxo_5.amount = 200
+ _utxo_5.block_number = 5
+ _utxo_5.block_timestamp = datetime.strptime(
+ "2021/12/31 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_5)
+
+ _utxo_6 = UTXO()
+ _utxo_6.transaction_hash = "tx6"
+ _utxo_6.account_address = user_address_2
+ _utxo_6.token_address = token_address_1
+ _utxo_6.amount = 20
+ _utxo_6.block_number = 6
+ _utxo_6.block_timestamp = datetime.strptime(
+ "2022/01/01 01:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_6)
+
+ _utxo_7 = UTXO()
+ _utxo_7.transaction_hash = "tx7"
+ _utxo_7.account_address = user_address_2
+ _utxo_7.token_address = token_address_1
+ _utxo_7.amount = 40
+ _utxo_7.block_number = 7
+ _utxo_7.block_timestamp = datetime.strptime(
+ "2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_utxo_7)
+
+ _utxo_8 = UTXO()
+ _utxo_8.transaction_hash = "tx8"
+ _utxo_8.account_address = user_address_2
+ _utxo_8.token_address = token_address_1
+ _utxo_8.amount = 2
+ _utxo_8.block_number = 8
+ _utxo_8.block_timestamp = datetime.strptime(
+ "2022/01/02 01:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_utxo_8)
+
+ _utxo_9 = UTXO()
+ _utxo_9.transaction_hash = "tx9"
+ _utxo_9.account_address = issuer_address
+ _utxo_9.token_address = token_address_1
+ _utxo_9.amount = 300
+ _utxo_9.block_number = 9
+ _utxo_9.block_timestamp = datetime.strptime(
+ "2021/12/31 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_9)
+
+ # Prepare data: Ledger template
+ _template = LedgerTemplate()
+ _template.token_address = token_address_1
+ _template.issuer_address = issuer_address
+ _template.token_name = "受益権テスト"
+ _template.headers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "テスト項目1": "テスト値1",
+ "テスト項目2": {
+ "テスト項目A": "テスト値2A",
+ "テスト項目B": "テスト値2B",
+ },
+ "テスト項目3": {
+ "テスト項目A": {"テスト項目a": "テスト値3Aa"},
+ "テスト項目B": "テスト値3B",
+ },
+ },
+ ]
+ _template.footers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "f-テスト項目1": "f-テスト値1",
+ "f-テスト項目2": {
+ "f-テスト項目A": "f-テスト値2A",
+ "f-テスト項目B": "f-テスト値2B",
+ },
+ "f-テスト項目3": {
+ "f-テスト項目A": {"f-テスト項目a": "f-テスト値3Aa"},
+ "f-テスト項目B": "f-テスト値3B",
+ },
+ },
+ ]
+ db.add(_template)
+
+ # Prepare data: Ledger template details 1
+ _details_1 = LedgerDetailsTemplate()
+ _details_1.token_address = token_address_1
+ _details_1.token_detail_type = "優先受益権"
+ _details_1.headers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test項目1": "test値1",
+ "test項目2": {
+ "test項目A": "test値2A",
+ },
+ },
+ ]
+ _details_1.footers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test-item1": "test-value1",
+ "test-item2": {"test-itemA": {"test-item": "test-value2Aa"}},
+ },
+ ]
+ _details_1.data_type = LedgerDetailsDataType.IBET_FIN.value
+ _details_1.data_source = token_address_1
+ db.add(_details_1)
+
+ # Prepare data: Ledger template details 2
+ _details_2 = LedgerDetailsTemplate()
+ _details_2.token_address = token_address_1
+ _details_2.token_detail_type = "劣後受益権"
+ _details_2.headers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "d-test項目1": "d-test値1",
+ "d-test項目2": "d-test値2",
+ },
+ ]
+ _details_2.footers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "f-d-test項目1": "d-test値1",
+ "f-d-test項目2": "d-test値2",
+ },
+ ]
+ _details_2.data_type = LedgerDetailsDataType.DB.value
+ _details_2.data_source = "data_id_2"
+ db.add(_details_2)
+
+ _details_2_data_1 = LedgerDetailsData()
+ _details_2_data_1.token_address = token_address_1
+ _details_2_data_1.data_id = "data_id_2"
+ _details_2_data_1.name = "test_data_name_1"
+ _details_2_data_1.address = "test_data_address_1"
+ _details_2_data_1.amount = 100
+ _details_2_data_1.price = 200
+ _details_2_data_1.balance = 20000
+ _details_2_data_1.acquisition_date = "2022/03/03"
+ db.add(_details_2_data_1)
+
+ _details_2_data_2 = LedgerDetailsData()
+ _details_2_data_2.token_address = token_address_1
+ _details_2_data_2.data_id = "data_id_2"
+ _details_2_data_2.name = "test_data_name_2"
+ _details_2_data_2.address = "test_data_address_2"
+ _details_2_data_2.amount = 30
+ _details_2_data_2.price = 40
+ _details_2_data_2.balance = 1200
+ _details_2_data_2.acquisition_date = "2022/12/03"
+ db.add(_details_2_data_2)
+
+ db.commit()
+
+ # Execute
+ await ledger_utils.create_ledger(token_address_1, async_db)
+ await async_db.commit()
+ await async_db.close()
+
+ # Assertion
+ _notifications = db.scalars(select(Notification)).all()
+ assert len(_notifications) == 1
+ _notification = db.scalars(select(Notification).limit(1)).first()
+ assert _notification.id == 1
+ assert _notification.notice_id is not None
+ assert _notification.issuer_address == issuer_address
+ assert _notification.priority == 0
+ assert _notification.type == NotificationType.CREATE_LEDGER_INFO
+ assert _notification.code == 0
+ assert _notification.metainfo == {
+ "token_address": token_address_1,
+ "token_type": TokenType.IBET_STRAIGHT_BOND.value,
+ "ledger_id": 1,
+ }
+ _ledger = db.scalars(select(Ledger).limit(1)).first()
+ assert _ledger.id == 1
+ assert _ledger.token_address == token_address_1
+ assert _ledger.token_type == TokenType.IBET_STRAIGHT_BOND.value
+ now_ymd = datetime.now(pytz.timezone(TZ)).strftime("%Y/%m/%d")
+ assert _ledger.ledger == {
+ "created": now_ymd,
+ "token_name": "受益権テスト",
+ "currency": "JPY",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "テスト項目1": "テスト値1",
+ "テスト項目2": {
+ "テスト項目A": "テスト値2A",
+ "テスト項目B": "テスト値2B",
+ },
+ "テスト項目3": {
+ "テスト項目A": {"テスト項目a": "テスト値3Aa"},
+ "テスト項目B": "テスト値3B",
+ },
+ },
+ ],
+ "details": [
+ {
+ "token_detail_type": "優先受益権",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test項目1": "test値1",
+ "test項目2": {
+ "test項目A": "test値2A",
+ },
+ },
+ ],
+ "data": [
+ {
+ "account_address": issuer_address,
+ "name": None,
+ "address": None,
+ "amount": 300,
+ "price": 20,
+ "balance": 300 * 20,
+ "acquisition_date": "2022/01/01",
+ },
+ {
+ "account_address": user_address_2,
+ "name": None,
+ "address": None,
+ "amount": 220,
+ "price": 20,
+ "balance": 220 * 20,
+ "acquisition_date": "2022/01/01",
+ },
+ {
+ "account_address": user_address_2,
+ "name": None,
+ "address": None,
+ "amount": 42,
+ "price": 20,
+ "balance": 42 * 20,
+ "acquisition_date": "2022/01/02",
+ },
+ {
+ "account_address": user_address_1,
+ "name": None,
+ "address": None,
+ "amount": 110,
+ "price": 20,
+ "balance": 110 * 20,
+ "acquisition_date": "2022/01/01",
+ },
+ {
+ "account_address": user_address_1,
+ "name": None,
+ "address": None,
+ "amount": 70,
+ "price": 20,
+ "balance": 70 * 20,
+ "acquisition_date": "2022/01/02",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test-item1": "test-value1",
+ "test-item2": {
+ "test-itemA": {"test-item": "test-value2Aa"}
+ },
+ },
+ ],
+ "some_personal_info_not_registered": True,
+ },
+ {
+ "token_detail_type": "劣後受益権",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "d-test項目1": "d-test値1",
+ "d-test項目2": "d-test値2",
+ },
+ ],
+ "data": [
+ {
+ "account_address": None,
+ "name": "test_data_name_1",
+ "address": "test_data_address_1",
+ "amount": 100,
+ "price": 200,
+ "balance": 20000,
+ "acquisition_date": "2022/03/03",
+ },
+ {
+ "account_address": None,
+ "name": "test_data_name_2",
+ "address": "test_data_address_2",
+ "amount": 30,
+ "price": 40,
+ "balance": 1200,
+ "acquisition_date": "2022/12/03",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "f-d-test項目1": "d-test値1",
+ "f-d-test項目2": "d-test値2",
+ },
+ ],
+ "some_personal_info_not_registered": False,
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "f-テスト項目1": "f-テスト値1",
+ "f-テスト項目2": {
+ "f-テスト項目A": "f-テスト値2A",
+ "f-テスト項目B": "f-テスト値2B",
+ },
+ "f-テスト項目3": {
+ "f-テスト項目A": {"f-テスト項目a": "f-テスト値3Aa"},
+ "f-テスト項目B": "f-テスト値3B",
+ },
+ },
+ ],
+ }
+ db.close()
+
+ #
+ # Bond Token
+ # require_personal_info_registered: False
+ # - Perform searches only on indexed personal information.
+ # - Even if personal information exists in the contract, it will not be referenced.
+ # No personal information indexed
+ # -> "some_personal_info_not_registered" = True
+ @pytest.mark.asyncio
+ async def test_normal_2_2(self, db, async_db):
+ issuer = config_eth_account("user5")
+ issuer_address = issuer["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=issuer["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_1 = config_eth_account("user1")
+ user_address_1 = user_1["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data: Issuer account settings
+ _account = Account()
+ _account.issuer_address = issuer_address
+ _account.keyfile = issuer["keyfile_json"]
+ _account.eoa_password = E2EEUtils.encrypt("password")
+ _account.rsa_private_key = issuer["rsa_private_key"]
+ _account.rsa_public_key = issuer["rsa_public_key"]
+ _account.rsa_passphrase = E2EEUtils.encrypt("password")
+ _account.rsa_status = AccountRsaStatus.SET.value
+ db.add(_account)
+
+ # Prepare data: Personal info contract
+ # - Registered data is not referenced
+ personal_info_contract_address = deploy_personal_info_contract(
+ issuer_address, issuer_private_key
+ )
+ await register_personal_info(
+ personal_info_contract_address,
+ _account,
+ [
+ {
+ "address": user_address_1,
+ "private_key": user_private_key_1,
+ "data": {
+ "name": "name_test_con_1",
+ "address": "address_test_con_1",
+ },
+ },
+ ],
+ )
+
+ # Prepare data: Token
+ token_address_1 = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract_address,
+ require_personal_info_registered=False,
+ )
+ _token_1 = Token()
+ _token_1.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token_1.tx_hash = ""
+ _token_1.issuer_address = issuer_address
+ _token_1.token_address = token_address_1
+ _token_1.abi = {}
+ _token_1.version = TokenVersion.V_24_06
+ db.add(_token_1)
+
+ # Prepare data: UTXO
+ # - user_1: "2022/01/01" = 100 + 10, "2022/01/02" = 30 + 40
+ _utxo_1 = UTXO()
+ _utxo_1.transaction_hash = "tx1"
+ _utxo_1.account_address = user_address_1
+ _utxo_1.token_address = token_address_1
+ _utxo_1.amount = 100
+ _utxo_1.block_number = 1
+ _utxo_1.block_timestamp = datetime.strptime(
+ "2021/12/31 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_1)
+
+ _utxo_2 = UTXO()
+ _utxo_2.transaction_hash = "tx2"
+ _utxo_2.account_address = user_address_1
+ _utxo_2.token_address = token_address_1
+ _utxo_2.amount = 10
+ _utxo_2.block_number = 2
+ _utxo_2.block_timestamp = datetime.strptime(
+ "2022/01/01 01:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/01
+ db.add(_utxo_2)
+
+ _utxo_3 = UTXO()
+ _utxo_3.transaction_hash = "tx3"
+ _utxo_3.account_address = user_address_1
+ _utxo_3.token_address = token_address_1
+ _utxo_3.amount = 30
+ _utxo_3.block_number = 3
+ _utxo_3.block_timestamp = datetime.strptime(
+ "2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_utxo_3)
+
+ _utxo_4 = UTXO()
+ _utxo_4.transaction_hash = "tx4"
+ _utxo_4.account_address = user_address_1
+ _utxo_4.token_address = token_address_1
+ _utxo_4.amount = 40
+ _utxo_4.block_number = 4
+ _utxo_4.block_timestamp = datetime.strptime(
+ "2022/01/02 01:20:30", "%Y/%m/%d %H:%M:%S"
+ ) # JST 2022/01/02
+ db.add(_utxo_4)
+
+ # Prepare data: Ledger template
+ _template = LedgerTemplate()
+ _template.token_address = token_address_1
+ _template.issuer_address = issuer_address
+ _template.token_name = "受益権テスト"
+ _template.headers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "テスト項目1": "テスト値1",
+ "テスト項目2": {
+ "テスト項目A": "テスト値2A",
+ "テスト項目B": "テスト値2B",
+ },
+ "テスト項目3": {
+ "テスト項目A": {"テスト項目a": "テスト値3Aa"},
+ "テスト項目B": "テスト値3B",
+ },
+ },
+ ]
+ _template.footers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "f-テスト項目1": "f-テスト値1",
+ "f-テスト項目2": {
+ "f-テスト項目A": "f-テスト値2A",
+ "f-テスト項目B": "f-テスト値2B",
+ },
+ "f-テスト項目3": {
+ "f-テスト項目A": {"f-テスト項目a": "f-テスト値3Aa"},
+ "f-テスト項目B": "f-テスト値3B",
+ },
+ },
+ ]
+ db.add(_template)
+
+ # Prepare data: Ledger template details 1
+ _details_1 = LedgerDetailsTemplate()
+ _details_1.token_address = token_address_1
+ _details_1.token_detail_type = "優先受益権"
+ _details_1.headers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test項目1": "test値1",
+ "test項目2": {
+ "test項目A": "test値2A",
+ },
+ },
+ ]
+ _details_1.footers = [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test-item1": "test-value1",
+ "test-item2": {"test-itemA": {"test-item": "test-value2Aa"}},
+ },
+ ]
+ _details_1.data_type = LedgerDetailsDataType.IBET_FIN.value
+ _details_1.data_source = token_address_1
+ db.add(_details_1)
+
+ db.commit()
+
+ # Execute
+ await ledger_utils.create_ledger(token_address_1, async_db)
+ await async_db.commit()
+ await async_db.close()
+
+ # Assertion
+ _notifications = db.scalars(select(Notification)).all()
+ assert len(_notifications) == 1
+
+ _notification = db.scalars(select(Notification).limit(1)).first()
+ assert _notification.id == 1
+ assert _notification.notice_id is not None
+ assert _notification.issuer_address == issuer_address
+ assert _notification.priority == 0
+ assert _notification.type == NotificationType.CREATE_LEDGER_INFO
+ assert _notification.code == 0
+ assert _notification.metainfo == {
+ "token_address": token_address_1,
+ "token_type": TokenType.IBET_STRAIGHT_BOND.value,
+ "ledger_id": 1,
+ }
+
+ _ledger = db.scalars(select(Ledger).limit(1)).first()
+ assert _ledger.id == 1
+ assert _ledger.token_address == token_address_1
+ assert _ledger.token_type == TokenType.IBET_STRAIGHT_BOND.value
+ now_ymd = datetime.now(pytz.timezone(TZ)).strftime("%Y/%m/%d")
+ assert _ledger.ledger == {
+ "created": now_ymd,
+ "token_name": "受益権テスト",
+ "currency": "JPY",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "テスト項目1": "テスト値1",
+ "テスト項目2": {
+ "テスト項目A": "テスト値2A",
+ "テスト項目B": "テスト値2B",
+ },
+ "テスト項目3": {
+ "テスト項目A": {"テスト項目a": "テスト値3Aa"},
+ "テスト項目B": "テスト値3B",
+ },
+ },
+ ],
+ "details": [
+ {
+ "token_detail_type": "優先受益権",
+ "headers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test項目1": "test値1",
+ "test項目2": {
+ "test項目A": "test値2A",
+ },
+ },
+ ],
+ "data": [
+ {
+ "account_address": user_address_1,
+ "name": None, # Not set
+ "address": None, # Not set
+ "amount": 110,
+ "price": 20,
+ "balance": 110 * 20,
+ "acquisition_date": "2022/01/01",
+ },
+ {
+ "account_address": user_address_1,
+ "name": None, # Not set
+ "address": None, # Not set
+ "amount": 70,
+ "price": 20,
+ "balance": 70 * 20,
+ "acquisition_date": "2022/01/02",
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "test-item1": "test-value1",
+ "test-item2": {
+ "test-itemA": {"test-item": "test-value2Aa"}
+ },
+ },
+ ],
+ "some_personal_info_not_registered": True,
+ },
+ ],
+ "footers": [
+ {
+ "key": "aaa",
+ "value": "bbb",
+ },
+ {
+ "f-テスト項目1": "f-テスト値1",
+ "f-テスト項目2": {
+ "f-テスト項目A": "f-テスト値2A",
+ "f-テスト項目B": "f-テスト値2B",
+ },
+ "f-テスト項目3": {
+ "f-テスト項目A": {"f-テスト項目a": "f-テスト値3Aa"},
+ "f-テスト項目B": "f-テスト値3B",
+ },
+ },
+ ],
+ }
+ db.close()
+
+ #
+ # Ledger template is not set
+ # -> Skip processing
+ @pytest.mark.asyncio
+ async def test_normal_3(self, db, async_db):
+ issuer = config_eth_account("user5")
+ issuer_address = issuer["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=issuer["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data: Token
+ token_address_1 = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ ZERO_ADDRESS,
+ require_personal_info_registered=True,
+ )
+ _token_1 = Token()
+ _token_1.type = TokenType.IBET_STRAIGHT_BOND.value
+ _token_1.tx_hash = ""
+ _token_1.issuer_address = issuer_address
+ _token_1.token_address = token_address_1
+ _token_1.abi = {}
+ _token_1.version = TokenVersion.V_24_06
+ db.add(_token_1)
+ db.commit()
+
+ # Execute
+ await ledger_utils.create_ledger(token_address_1, async_db)
+ await async_db.commit()
+ await async_db.close()
+
+ # Assertion
+ _notifications = db.scalars(select(Notification)).all()
+ assert len(_notifications) == 0
+ _ledger = db.scalars(select(Ledger).limit(1)).first()
+ assert _ledger is None
+ db.close()
+
+ #
+ # Not a token type to be processed
+ # -> Skip processing
+ @pytest.mark.asyncio
+ async def test_normal_4(self, db, async_db):
+ issuer = config_eth_account("user5")
+ issuer_address = issuer["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=issuer["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data: Token
+ token_address_1 = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ ZERO_ADDRESS,
+ require_personal_info_registered=True,
+ )
+ _token_1 = Token()
+ _token_1.type = "IbetCoupon" # Not subject to processing
+ _token_1.tx_hash = ""
+ _token_1.issuer_address = issuer_address
+ _token_1.token_address = token_address_1
+ _token_1.abi = {}
+ _token_1.version = TokenVersion.V_24_06
+ db.add(_token_1)
+
+ db.commit()
+
+ # Execute
+ await ledger_utils.create_ledger(token_address_1, async_db)
+ await async_db.commit()
+ await async_db.close()
+
+ # assertion
+ _notifications = db.scalars(select(Notification)).all()
+ assert len(_notifications) == 0
+ _ledger = db.scalars(select(Ledger).limit(1)).first()
+ assert _ledger is None
+ db.close()
+
+ ###########################################################################
+ # Error Case
+ ###########################################################################
diff --git a/tests/test_batch_indexer_block_tx_data.py b/tests/batch/test_indexer_block_tx_data.py
similarity index 97%
rename from tests/test_batch_indexer_block_tx_data.py
rename to tests/batch/test_indexer_block_tx_data.py
index ac4d8115..781aa0fe 100644
--- a/tests/test_batch_indexer_block_tx_data.py
+++ b/tests/batch/test_indexer_block_tx_data.py
@@ -27,7 +27,7 @@
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.ext.asyncio import AsyncSession
from web3 import Web3
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
from web3.types import RPCEndpoint
from app.exceptions import ServiceUnavailableError
@@ -36,10 +36,10 @@
from batch.indexer_block_tx_data import LOG
from config import CHAIN_ID, WEB3_HTTP_PROVIDER, ZERO_ADDRESS
from tests.account_config import config_eth_account
-from tests.utils.contract_utils import IbetStandardTokenUtils
+from tests.contract_utils import IbetStandardTokenUtils
web3 = Web3(Web3.HTTPProvider(WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
@pytest.fixture(scope="function")
@@ -272,7 +272,7 @@ async def test_error_1(self, processor, db):
# Execute batch processing
with mock.patch(
- "web3.providers.async_rpc.AsyncHTTPProvider.make_request",
+ "web3.providers.rpc.async_rpc.AsyncHTTPProvider.make_request",
MagicMock(side_effect=ServiceUnavailableError()),
), pytest.raises(ServiceUnavailableError):
await processor.process()
diff --git a/tests/batch/test_indexer_delivery.py b/tests/batch/test_indexer_delivery.py
new file mode 100644
index 00000000..06073834
--- /dev/null
+++ b/tests/batch/test_indexer_delivery.py
@@ -0,0 +1,1809 @@
+"""
+Copyright BOOSTRY Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SPDX-License-Identifier: Apache-2.0
+"""
+
+import logging
+from datetime import UTC, datetime
+from unittest import mock
+from unittest.mock import patch
+
+import pytest
+from eth_keyfile import decode_keyfile_json
+from sqlalchemy import select
+from sqlalchemy.exc import SQLAlchemyError
+from sqlalchemy.ext.asyncio import AsyncSession
+from sqlalchemy.orm import Session
+
+from app.exceptions import ServiceUnavailableError
+from app.model.blockchain import IbetShareContract, IbetStraightBondContract
+from app.model.blockchain.tx_params.ibet_share import (
+ UpdateParams as IbetShareUpdateParams,
+)
+from app.model.blockchain.tx_params.ibet_straight_bond import (
+ UpdateParams as IbetStraightBondUpdateParams,
+)
+from app.model.db import (
+ Account,
+ DeliveryStatus,
+ IDXDelivery,
+ IDXDeliveryBlockNumber,
+ Notification,
+ NotificationType,
+ Token,
+ TokenType,
+ TokenVersion,
+)
+from app.utils.contract_utils import ContractUtils
+from app.utils.e2ee_utils import E2EEUtils
+from app.utils.web3_utils import AsyncWeb3Wrapper, Web3Wrapper
+from batch.indexer_delivery import LOG, Processor, main
+from config import CHAIN_ID, TX_GAS_LIMIT
+from tests.account_config import config_eth_account
+from tests.contract_utils import (
+ IbetSecurityTokenContractTestUtils as STContractUtils,
+ IbetSecurityTokenEscrowContractTestUtils as STEscrowContractUtils,
+ PersonalInfoContractTestUtils,
+)
+
+web3 = AsyncWeb3Wrapper()
+
+
+@pytest.fixture(scope="function")
+def main_func():
+ LOG = logging.getLogger("background")
+ default_log_level = LOG.level
+ LOG.setLevel(logging.DEBUG)
+ LOG.propagate = True
+ yield main
+ LOG.propagate = False
+ LOG.setLevel(default_log_level)
+
+
+@pytest.fixture(scope="function")
+def processor(db, caplog: pytest.LogCaptureFixture):
+ LOG = logging.getLogger("background")
+ default_log_level = LOG.level
+ LOG.setLevel(logging.DEBUG)
+ LOG.propagate = True
+ yield Processor()
+ LOG.propagate = False
+ LOG.setLevel(default_log_level)
+
+
+async def deploy_bond_token_contract(
+ address,
+ private_key,
+ personal_info_contract_address,
+ tradable_exchange_contract_address=None,
+ transfer_approval_required=None,
+):
+ arguments = [
+ "token.name",
+ "token.symbol",
+ 100,
+ 20,
+ "JPY",
+ "token.redemption_date",
+ 30,
+ "JPY",
+ "token.return_date",
+ "token.return_amount",
+ "token.purpose",
+ ]
+ bond_contrat = IbetStraightBondContract()
+ token_address, _, _ = await bond_contrat.create(arguments, address, private_key)
+ await bond_contrat.update(
+ data=IbetStraightBondUpdateParams(
+ transferable=True,
+ personal_info_contract_address=personal_info_contract_address,
+ tradable_exchange_contract_address=tradable_exchange_contract_address,
+ transfer_approval_required=transfer_approval_required,
+ ),
+ tx_from=address,
+ private_key=private_key,
+ )
+
+ return ContractUtils.get_contract("IbetStraightBond", token_address)
+
+
+async def deploy_share_token_contract(
+ address,
+ private_key,
+ personal_info_contract_address,
+ tradable_exchange_contract_address=None,
+ transfer_approval_required=None,
+):
+ arguments = [
+ "token.name",
+ "token.symbol",
+ 20,
+ 100,
+ 3,
+ "token.dividend_record_date",
+ "token.dividend_payment_date",
+ "token.cancellation_date",
+ 30,
+ ]
+ share_contract = IbetShareContract()
+ token_address, _, _ = await share_contract.create(arguments, address, private_key)
+ await share_contract.update(
+ data=IbetShareUpdateParams(
+ transferable=True,
+ personal_info_contract_address=personal_info_contract_address,
+ tradable_exchange_contract_address=tradable_exchange_contract_address,
+ transfer_approval_required=transfer_approval_required,
+ ),
+ tx_from=address,
+ private_key=private_key,
+ )
+
+ return ContractUtils.get_contract("IbetShare", token_address)
+
+
+class TestProcessor:
+ ###########################################################################
+ # Normal Case
+ ###########################################################################
+
+ #
+ # No event log
+ # - Token not yet issued
+ @pytest.mark.asyncio
+ async def test_normal_1_1(
+ self,
+ processor,
+ db,
+ personal_info_contract,
+ ibet_security_token_dvp_contract,
+ caplog: pytest.LogCaptureFixture,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.rsa_private_key = user_1["rsa_private_key"]
+ account.rsa_public_key = user_1["rsa_public_key"]
+ account.rsa_passphrase = E2EEUtils.encrypt("password")
+ account.rsa_status = 3
+ db.add(account)
+
+ # Prepare data : Token(processing token)
+ token_1 = Token()
+ token_1.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_1.token_address = "test1"
+ token_1.issuer_address = issuer_address
+ token_1.abi = "abi"
+ token_1.tx_hash = "tx_hash"
+ token_1.token_status = 0
+ token_1.version = TokenVersion.V_24_06
+ db.add(token_1)
+
+ db.commit()
+
+ # Run target process
+ block_number = await web3.eth.block_number
+ await processor.sync_new_logs()
+
+ # Assertion
+ _delivery_list = db.scalars(select(IDXDelivery)).all()
+ assert len(_delivery_list) == 0
+
+ _idx_delivery_block_number = db.scalars(
+ select(IDXDeliveryBlockNumber).limit(1)
+ ).first()
+ assert _idx_delivery_block_number is None
+
+ #
+ # No event log
+ # - Issued tokens but no exchange address is set.
+ @pytest.mark.asyncio
+ async def test_normal_1_2(
+ self, processor, db, personal_info_contract, caplog: pytest.LogCaptureFixture
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.rsa_private_key = user_1["rsa_private_key"]
+ account.rsa_public_key = user_1["rsa_public_key"]
+ account.rsa_passphrase = E2EEUtils.encrypt("password")
+ account.rsa_status = 3
+ db.add(account)
+
+ # Prepare data : Token
+ token_contract_1 = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=None,
+ )
+ token_address_1 = token_contract_1.address
+ token_1 = Token()
+ token_1.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_1.token_address = token_address_1
+ token_1.issuer_address = issuer_address
+ token_1.abi = token_contract_1.abi
+ token_1.tx_hash = "tx_hash"
+ token_1.version = TokenVersion.V_24_06
+ db.add(token_1)
+
+ # Prepare data : Token(processing token)
+ token_2 = Token()
+ token_2.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_2.token_address = "test1"
+ token_2.issuer_address = issuer_address
+ token_2.abi = "abi"
+ token_2.tx_hash = "tx_hash"
+ token_2.token_status = 0
+ token_2.version = TokenVersion.V_24_06
+ db.add(token_2)
+
+ db.commit()
+
+ # Run target process
+ block_number = await web3.eth.block_number
+ await processor.sync_new_logs()
+
+ # Assertion
+ _delivery_list = db.scalars(select(IDXDelivery)).all()
+ assert len(_delivery_list) == 0
+
+ _idx_delivery_block_number = db.scalars(
+ select(IDXDeliveryBlockNumber).limit(1)
+ ).first()
+ assert _idx_delivery_block_number is None
+
+ #
+ # No event log
+ # - Issued tokens but the exchange contract other than DVP contract is set.
+ @pytest.mark.asyncio
+ async def test_normal_1_3(
+ self,
+ processor,
+ db,
+ personal_info_contract,
+ ibet_security_token_escrow_contract,
+ caplog: pytest.LogCaptureFixture,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.rsa_private_key = user_1["rsa_private_key"]
+ account.rsa_public_key = user_1["rsa_public_key"]
+ account.rsa_passphrase = E2EEUtils.encrypt("password")
+ account.rsa_status = 3
+ db.add(account)
+
+ # Prepare data : Token
+ token_contract_1 = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_escrow_contract.address,
+ )
+ token_address_1 = token_contract_1.address
+ token_1 = Token()
+ token_1.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_1.token_address = token_address_1
+ token_1.issuer_address = issuer_address
+ token_1.abi = token_contract_1.abi
+ token_1.tx_hash = "tx_hash"
+ token_1.version = TokenVersion.V_24_06
+ db.add(token_1)
+
+ # Prepare data : Token(processing token)
+ token_2 = Token()
+ token_2.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_2.token_address = "test1"
+ token_2.issuer_address = issuer_address
+ token_2.abi = "abi"
+ token_2.tx_hash = "tx_hash"
+ token_2.token_status = 0
+ token_2.version = TokenVersion.V_24_06
+ db.add(token_2)
+
+ db.commit()
+
+ # Run target process
+ block_number = await web3.eth.block_number
+ await processor.sync_new_logs()
+
+ # Assertion
+ _delivery_list = db.scalars(select(IDXDelivery)).all()
+ assert len(_delivery_list) == 0
+
+ _idx_delivery_block_number = db.scalars(
+ select(IDXDeliveryBlockNumber).limit(1)
+ ).first()
+ assert _idx_delivery_block_number.latest_block_number == block_number
+ assert (
+ _idx_delivery_block_number.exchange_address
+ == ibet_security_token_escrow_contract.address
+ )
+
+ assert (
+ caplog.record_tuples.count(
+ (
+ LOG.name,
+ logging.INFO,
+ f"Syncing from=1, to={block_number}, exchange={ibet_security_token_escrow_contract.address}",
+ )
+ )
+ == 1
+ )
+
+ #
+ # Event log
+ # - Exchange: CreateDelivery (from issuer)
+ @pytest.mark.asyncio
+ async def test_normal_2_1(
+ self,
+ processor,
+ db,
+ personal_info_contract,
+ ibet_security_token_dvp_contract,
+ caplog: pytest.LogCaptureFixture,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ agent_address = user_3["address"]
+ agent_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = user_1["keyfile_json"]
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ # Prepare data : Token
+ token_contract_1 = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ )
+ token_address_1 = token_contract_1.address
+ token_1 = Token()
+ token_1.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_1.token_address = token_address_1
+ token_1.issuer_address = issuer_address
+ token_1.abi = token_contract_1.abi
+ token_1.tx_hash = "tx_hash"
+ token_1.version = TokenVersion.V_24_06
+ db.add(token_1)
+
+ # Prepare data : Token(processing token)
+ token_2 = Token()
+ token_2.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_2.token_address = "test1"
+ token_2.issuer_address = issuer_address
+ token_2.abi = "abi"
+ token_2.tx_hash = "tx_hash"
+ token_2.token_status = 0
+ token_2.version = TokenVersion.V_24_06
+ db.add(token_2)
+
+ # Prepare data : BlockNumber
+ _idx_delivery_block_number = IDXDeliveryBlockNumber()
+ _idx_delivery_block_number.latest_block_number = 0
+ _idx_delivery_block_number.exchange_address = (
+ ibet_security_token_dvp_contract.address
+ )
+ db.add(_idx_delivery_block_number)
+
+ db.commit()
+
+ # Transfer
+ tx = token_contract_1.functions.transferFrom(
+ issuer_address, ibet_security_token_dvp_contract.address, 40
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # CreateDelivery
+ tx = ibet_security_token_dvp_contract.functions.createDelivery(
+ token_address_1, user_address_1, 30, agent_address, "." * 1000
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ tx_hash_1, tx_receipt_1 = ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # Run target process
+ block_number = await web3.eth.block_number
+ await processor.sync_new_logs()
+
+ # Assertion
+ _delivery_list = db.scalars(select(IDXDelivery)).all()
+ assert len(_delivery_list) == 1
+ _delivery = _delivery_list[0]
+ assert _delivery.id == 1
+ assert _delivery.exchange_address == ibet_security_token_dvp_contract.address
+ assert _delivery.token_address == token_address_1
+ assert _delivery.buyer_address == user_address_1
+ assert _delivery.seller_address == issuer_address
+ assert _delivery.amount == 30
+ assert _delivery.agent_address == agent_address
+ assert _delivery.data == "." * 1000
+ block = await web3.eth.get_block(tx_receipt_1["blockNumber"])
+ assert _delivery.create_blocktimestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
+ assert _delivery.create_transaction_hash == tx_hash_1
+ assert _delivery.cancel_blocktimestamp is None
+ assert _delivery.cancel_transaction_hash is None
+ assert _delivery.confirm_blocktimestamp is None
+ assert _delivery.confirm_transaction_hash is None
+ assert _delivery.finish_blocktimestamp is None
+ assert _delivery.finish_transaction_hash is None
+ assert _delivery.abort_blocktimestamp is None
+ assert _delivery.abort_transaction_hash is None
+ assert _delivery.confirmed is False
+ assert _delivery.valid is True
+ assert _delivery.status == DeliveryStatus.DELIVERY_CREATED
+
+ _idx_delivery_block_number = db.scalars(
+ select(IDXDeliveryBlockNumber).limit(1)
+ ).first()
+ assert (
+ _idx_delivery_block_number.exchange_address
+ == ibet_security_token_dvp_contract.address
+ )
+ assert _idx_delivery_block_number.latest_block_number == block_number
+
+ assert (
+ caplog.record_tuples.count(
+ (
+ LOG.name,
+ logging.INFO,
+ f"Syncing from=1, to={block_number}, exchange={ibet_security_token_dvp_contract.address}",
+ )
+ )
+ == 1
+ )
+
+ #
+ # Event log
+ # - Exchange: CancelDelivery (from issuer)
+ @pytest.mark.asyncio
+ async def test_normal_2_2_1(
+ self,
+ processor,
+ db,
+ personal_info_contract,
+ ibet_security_token_dvp_contract,
+ caplog: pytest.LogCaptureFixture,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ agent_address = user_3["address"]
+ agent_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = user_1["keyfile_json"]
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ # Prepare data : Token
+ token_contract_1 = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ )
+ token_address_1 = token_contract_1.address
+ token_1 = Token()
+ token_1.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_1.token_address = token_address_1
+ token_1.issuer_address = issuer_address
+ token_1.abi = token_contract_1.abi
+ token_1.tx_hash = "tx_hash"
+ token_1.version = TokenVersion.V_24_06
+ db.add(token_1)
+
+ # Prepare data : Token(processing token)
+ token_2 = Token()
+ token_2.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_2.token_address = "test1"
+ token_2.issuer_address = issuer_address
+ token_2.abi = "abi"
+ token_2.tx_hash = "tx_hash"
+ token_2.token_status = 0
+ token_2.version = TokenVersion.V_24_06
+ db.add(token_2)
+
+ # Prepare data : BlockNumber
+ _idx_delivery_block_number = IDXDeliveryBlockNumber()
+ _idx_delivery_block_number.latest_block_number = 0
+ _idx_delivery_block_number.exchange_address = (
+ ibet_security_token_dvp_contract.address
+ )
+ db.add(_idx_delivery_block_number)
+
+ db.commit()
+
+ # Transfer
+ tx = token_contract_1.functions.transferFrom(
+ issuer_address, ibet_security_token_dvp_contract.address, 40
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # CreateDelivery
+ tx = ibet_security_token_dvp_contract.functions.createDelivery(
+ token_address_1, user_address_1, 30, agent_address, "." * 1000
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ tx_hash_1, tx_receipt_1 = ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # CancelDelivery
+ tx = ibet_security_token_dvp_contract.functions.cancelDelivery(
+ 1
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ tx_hash_2, tx_receipt_2 = ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # Run target process
+ block_number = await web3.eth.block_number
+ await processor.sync_new_logs()
+
+ # Assertion
+ _delivery_list = db.scalars(select(IDXDelivery)).all()
+ assert len(_delivery_list) == 1
+ _delivery = _delivery_list[0]
+ assert _delivery.id == 1
+ assert _delivery.exchange_address == ibet_security_token_dvp_contract.address
+ assert _delivery.token_address == token_address_1
+ assert _delivery.buyer_address == user_address_1
+ assert _delivery.seller_address == issuer_address
+ assert _delivery.amount == 30
+ assert _delivery.agent_address == agent_address
+ assert _delivery.data == "." * 1000
+ block = await web3.eth.get_block(tx_receipt_1["blockNumber"])
+ assert _delivery.create_blocktimestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
+ assert _delivery.create_transaction_hash == tx_hash_1
+ block = await web3.eth.get_block(tx_receipt_2["blockNumber"])
+ assert _delivery.cancel_blocktimestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
+ assert _delivery.cancel_transaction_hash == tx_hash_2
+ assert _delivery.confirm_blocktimestamp is None
+ assert _delivery.confirm_transaction_hash is None
+ assert _delivery.finish_blocktimestamp is None
+ assert _delivery.finish_transaction_hash is None
+ assert _delivery.abort_blocktimestamp is None
+ assert _delivery.abort_transaction_hash is None
+ assert _delivery.confirmed is False
+ assert _delivery.valid is False
+ assert _delivery.status == DeliveryStatus.DELIVERY_CANCELED
+
+ _idx_delivery_block_number = db.scalars(
+ select(IDXDeliveryBlockNumber).limit(1)
+ ).first()
+ assert (
+ _idx_delivery_block_number.exchange_address
+ == ibet_security_token_dvp_contract.address
+ )
+ assert _idx_delivery_block_number.latest_block_number == block_number
+
+ assert (
+ caplog.record_tuples.count(
+ (
+ LOG.name,
+ logging.INFO,
+ f"Syncing from=1, to={block_number}, exchange={ibet_security_token_dvp_contract.address}",
+ )
+ )
+ == 1
+ )
+
+ #
+ # Event log
+ # - Exchange: CancelDelivery (from buyer)
+ @pytest.mark.asyncio
+ async def test_normal_2_2_2(
+ self,
+ processor,
+ db,
+ personal_info_contract,
+ ibet_security_token_dvp_contract,
+ caplog: pytest.LogCaptureFixture,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ agent_address = user_3["address"]
+ agent_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = user_1["keyfile_json"]
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ # Prepare data : Token
+ token_contract_1 = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ )
+ token_address_1 = token_contract_1.address
+ token_1 = Token()
+ token_1.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_1.token_address = token_address_1
+ token_1.issuer_address = issuer_address
+ token_1.abi = token_contract_1.abi
+ token_1.tx_hash = "tx_hash"
+ token_1.version = TokenVersion.V_24_06
+ db.add(token_1)
+
+ # Prepare data : Token(processing token)
+ token_2 = Token()
+ token_2.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_2.token_address = "test1"
+ token_2.issuer_address = issuer_address
+ token_2.abi = "abi"
+ token_2.tx_hash = "tx_hash"
+ token_2.token_status = 0
+ token_2.version = TokenVersion.V_24_06
+ db.add(token_2)
+
+ # Prepare data : BlockNumber
+ _idx_delivery_block_number = IDXDeliveryBlockNumber()
+ _idx_delivery_block_number.latest_block_number = 0
+ _idx_delivery_block_number.exchange_address = (
+ ibet_security_token_dvp_contract.address
+ )
+ db.add(_idx_delivery_block_number)
+
+ db.commit()
+
+ # Transfer
+ tx = token_contract_1.functions.transferFrom(
+ issuer_address, ibet_security_token_dvp_contract.address, 40
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # CreateDelivery
+ tx = ibet_security_token_dvp_contract.functions.createDelivery(
+ token_address_1, user_address_1, 30, agent_address, "." * 1000
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ tx_hash_1, tx_receipt_1 = ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # CancelDelivery
+ tx = ibet_security_token_dvp_contract.functions.cancelDelivery(
+ 1
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": user_address_1,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ tx_hash_2, tx_receipt_2 = ContractUtils.send_transaction(tx, user_private_key_1)
+
+ # Run target process
+ block_number = await web3.eth.block_number
+ await processor.sync_new_logs()
+
+ # Assertion
+ _delivery_list = db.scalars(select(IDXDelivery)).all()
+ assert len(_delivery_list) == 1
+ _delivery = _delivery_list[0]
+ assert _delivery.id == 1
+ assert _delivery.exchange_address == ibet_security_token_dvp_contract.address
+ assert _delivery.token_address == token_address_1
+ assert _delivery.buyer_address == user_address_1
+ assert _delivery.seller_address == issuer_address
+ assert _delivery.amount == 30
+ assert _delivery.agent_address == agent_address
+ assert _delivery.data == "." * 1000
+ block = await web3.eth.get_block(tx_receipt_1["blockNumber"])
+ assert _delivery.create_blocktimestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
+ assert _delivery.create_transaction_hash == tx_hash_1
+ block = await web3.eth.get_block(tx_receipt_2["blockNumber"])
+ assert _delivery.cancel_blocktimestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
+ assert _delivery.cancel_transaction_hash == tx_hash_2
+ assert _delivery.confirm_blocktimestamp is None
+ assert _delivery.confirm_transaction_hash is None
+ assert _delivery.finish_blocktimestamp is None
+ assert _delivery.finish_transaction_hash is None
+ assert _delivery.abort_blocktimestamp is None
+ assert _delivery.abort_transaction_hash is None
+ assert _delivery.confirmed is False
+ assert _delivery.valid is False
+ assert _delivery.status == DeliveryStatus.DELIVERY_CANCELED
+
+ _idx_delivery_block_number = db.scalars(
+ select(IDXDeliveryBlockNumber).limit(1)
+ ).first()
+ assert (
+ _idx_delivery_block_number.exchange_address
+ == ibet_security_token_dvp_contract.address
+ )
+ assert _idx_delivery_block_number.latest_block_number == block_number
+
+ assert (
+ caplog.record_tuples.count(
+ (
+ LOG.name,
+ logging.INFO,
+ f"Syncing from=1, to={block_number}, exchange={ibet_security_token_dvp_contract.address}",
+ )
+ )
+ == 1
+ )
+
+ #
+ # Event log
+ # - Exchange: ConfirmDelivery (from buyer)
+ @pytest.mark.freeze_time("2021-04-27 12:34:56")
+ @pytest.mark.asyncio
+ async def test_normal_2_3(
+ self,
+ processor,
+ db,
+ personal_info_contract,
+ ibet_security_token_dvp_contract,
+ caplog: pytest.LogCaptureFixture,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ agent_address = user_3["address"]
+ agent_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = user_1["keyfile_json"]
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ # Prepare data : Token
+ token_contract_1 = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ )
+ token_address_1 = token_contract_1.address
+ token_1 = Token()
+ token_1.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_1.token_address = token_address_1
+ token_1.issuer_address = issuer_address
+ token_1.abi = token_contract_1.abi
+ token_1.tx_hash = "tx_hash"
+ token_1.version = TokenVersion.V_24_06
+ db.add(token_1)
+
+ # Prepare data : Token(processing token)
+ token_2 = Token()
+ token_2.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_2.token_address = "test1"
+ token_2.issuer_address = issuer_address
+ token_2.abi = "abi"
+ token_2.tx_hash = "tx_hash"
+ token_2.token_status = 0
+ token_2.version = TokenVersion.V_24_06
+ db.add(token_2)
+
+ # Prepare data : BlockNumber
+ _idx_delivery_block_number = IDXDeliveryBlockNumber()
+ _idx_delivery_block_number.latest_block_number = 0
+ _idx_delivery_block_number.exchange_address = (
+ ibet_security_token_dvp_contract.address
+ )
+ db.add(_idx_delivery_block_number)
+
+ db.commit()
+
+ # Transfer
+ tx = token_contract_1.functions.transferFrom(
+ issuer_address, ibet_security_token_dvp_contract.address, 40
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # CreateDelivery
+ tx = ibet_security_token_dvp_contract.functions.createDelivery(
+ token_address_1, user_address_1, 30, agent_address, "." * 1000
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ tx_hash_1, tx_receipt_1 = ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # ConfirmDelivery
+ tx = ibet_security_token_dvp_contract.functions.confirmDelivery(
+ 1
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": user_address_1,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ tx_hash_2, tx_receipt_2 = ContractUtils.send_transaction(tx, user_private_key_1)
+
+ # Run target process
+ block_number = await web3.eth.block_number
+ await processor.sync_new_logs()
+
+ # Assertion
+ _delivery_list = db.scalars(select(IDXDelivery)).all()
+ assert len(_delivery_list) == 1
+ _delivery = _delivery_list[0]
+ assert _delivery.id == 1
+ assert _delivery.exchange_address == ibet_security_token_dvp_contract.address
+ assert _delivery.token_address == token_address_1
+ assert _delivery.buyer_address == user_address_1
+ assert _delivery.seller_address == issuer_address
+ assert _delivery.amount == 30
+ assert _delivery.agent_address == agent_address
+ assert _delivery.data == "." * 1000
+ block = await web3.eth.get_block(tx_receipt_1["blockNumber"])
+ assert _delivery.create_blocktimestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
+ assert _delivery.create_transaction_hash == tx_hash_1
+ assert _delivery.cancel_blocktimestamp is None
+ assert _delivery.cancel_transaction_hash is None
+ block = await web3.eth.get_block(tx_receipt_2["blockNumber"])
+ assert _delivery.confirm_blocktimestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
+ assert _delivery.confirm_transaction_hash == tx_hash_2
+ assert _delivery.finish_blocktimestamp is None
+ assert _delivery.finish_transaction_hash is None
+ assert _delivery.abort_blocktimestamp is None
+ assert _delivery.abort_transaction_hash is None
+ assert _delivery.confirmed is True
+ assert _delivery.valid is True
+ assert _delivery.status == DeliveryStatus.DELIVERY_CONFIRMED
+
+ _idx_delivery_block_number = db.scalars(
+ select(IDXDeliveryBlockNumber).limit(1)
+ ).first()
+ assert (
+ _idx_delivery_block_number.exchange_address
+ == ibet_security_token_dvp_contract.address
+ )
+ assert _idx_delivery_block_number.latest_block_number == block_number
+
+ assert (
+ caplog.record_tuples.count(
+ (
+ LOG.name,
+ logging.INFO,
+ f"Syncing from=1, to={block_number}, exchange={ibet_security_token_dvp_contract.address}",
+ )
+ )
+ == 1
+ )
+
+ #
+ # Event log
+ # - Exchange: FinishDelivery (from agent)
+ @pytest.mark.freeze_time("2021-04-27 12:34:56")
+ @pytest.mark.asyncio
+ async def test_normal_2_4(
+ self,
+ processor,
+ db,
+ personal_info_contract,
+ ibet_security_token_dvp_contract,
+ caplog: pytest.LogCaptureFixture,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ agent_address = user_3["address"]
+ agent_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = user_1["keyfile_json"]
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ # Prepare data : Token
+ token_contract_1 = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ )
+ token_address_1 = token_contract_1.address
+ token_1 = Token()
+ token_1.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_1.token_address = token_address_1
+ token_1.issuer_address = issuer_address
+ token_1.abi = token_contract_1.abi
+ token_1.tx_hash = "tx_hash"
+ token_1.version = TokenVersion.V_24_06
+ db.add(token_1)
+
+ # Prepare data : Token(processing token)
+ token_2 = Token()
+ token_2.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_2.token_address = "test1"
+ token_2.issuer_address = issuer_address
+ token_2.abi = "abi"
+ token_2.tx_hash = "tx_hash"
+ token_2.token_status = 0
+ token_2.version = TokenVersion.V_24_06
+ db.add(token_2)
+
+ # Prepare data : BlockNumber
+ _idx_delivery_block_number = IDXDeliveryBlockNumber()
+ _idx_delivery_block_number.latest_block_number = 0
+ _idx_delivery_block_number.exchange_address = (
+ ibet_security_token_dvp_contract.address
+ )
+ db.add(_idx_delivery_block_number)
+
+ db.commit()
+
+ # Transfer
+ tx = token_contract_1.functions.transferFrom(
+ issuer_address, ibet_security_token_dvp_contract.address, 40
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # CreateDelivery
+ tx = ibet_security_token_dvp_contract.functions.createDelivery(
+ token_address_1, user_address_1, 30, agent_address, "." * 1000
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ tx_hash_1, tx_receipt_1 = ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # ConfirmDelivery
+ tx = ibet_security_token_dvp_contract.functions.confirmDelivery(
+ 1
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": user_address_1,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ tx_hash_2, tx_receipt_2 = ContractUtils.send_transaction(tx, user_private_key_1)
+
+ # FinishDelivery
+ tx = ibet_security_token_dvp_contract.functions.finishDelivery(
+ 1
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": agent_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ tx_hash_3, tx_receipt_3 = ContractUtils.send_transaction(tx, agent_private_key)
+
+ # Run target process
+ block_number = await web3.eth.block_number
+ await processor.sync_new_logs()
+
+ # Assertion
+ _delivery_list = db.scalars(select(IDXDelivery)).all()
+ assert len(_delivery_list) == 1
+ _delivery = _delivery_list[0]
+ assert _delivery.id == 1
+ assert _delivery.exchange_address == ibet_security_token_dvp_contract.address
+ assert _delivery.token_address == token_address_1
+ assert _delivery.buyer_address == user_address_1
+ assert _delivery.seller_address == issuer_address
+ assert _delivery.amount == 30
+ assert _delivery.agent_address == agent_address
+ assert _delivery.data == "." * 1000
+ block = await web3.eth.get_block(tx_receipt_1["blockNumber"])
+ assert _delivery.create_blocktimestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
+ assert _delivery.create_transaction_hash == tx_hash_1
+ assert _delivery.cancel_blocktimestamp is None
+ assert _delivery.cancel_transaction_hash is None
+ block = await web3.eth.get_block(tx_receipt_2["blockNumber"])
+ assert _delivery.confirm_blocktimestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
+ assert _delivery.confirm_transaction_hash == tx_hash_2
+ block = await web3.eth.get_block(tx_receipt_3["blockNumber"])
+ assert _delivery.finish_blocktimestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
+ assert _delivery.finish_transaction_hash == tx_hash_3
+ assert _delivery.abort_blocktimestamp is None
+ assert _delivery.abort_transaction_hash is None
+ assert _delivery.confirmed is True
+ assert _delivery.valid is False
+ assert _delivery.status == DeliveryStatus.DELIVERY_FINISHED
+
+ _idx_delivery_block_number = db.scalars(
+ select(IDXDeliveryBlockNumber).limit(1)
+ ).first()
+ assert (
+ _idx_delivery_block_number.exchange_address
+ == ibet_security_token_dvp_contract.address
+ )
+ assert _idx_delivery_block_number.latest_block_number == block_number
+
+ assert (
+ caplog.record_tuples.count(
+ (
+ LOG.name,
+ logging.INFO,
+ f"Syncing from=1, to={block_number}, exchange={ibet_security_token_dvp_contract.address}",
+ )
+ )
+ == 1
+ )
+
+ #
+ # Event log
+ # - Exchange: AbortDelivery (from agent)
+ @pytest.mark.asyncio
+ async def test_normal_2_5(
+ self,
+ processor,
+ db,
+ personal_info_contract,
+ ibet_security_token_dvp_contract,
+ caplog: pytest.LogCaptureFixture,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ agent_address = user_3["address"]
+ agent_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = user_1["keyfile_json"]
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ # Prepare data : Token
+ token_contract_1 = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ )
+ token_address_1 = token_contract_1.address
+ token_1 = Token()
+ token_1.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_1.token_address = token_address_1
+ token_1.issuer_address = issuer_address
+ token_1.abi = token_contract_1.abi
+ token_1.tx_hash = "tx_hash"
+ token_1.version = TokenVersion.V_24_06
+ db.add(token_1)
+
+ # Prepare data : Token(processing token)
+ token_2 = Token()
+ token_2.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_2.token_address = "test1"
+ token_2.issuer_address = issuer_address
+ token_2.abi = "abi"
+ token_2.tx_hash = "tx_hash"
+ token_2.token_status = 0
+ token_2.version = TokenVersion.V_24_06
+ db.add(token_2)
+
+ # Prepare data : BlockNumber
+ _idx_delivery_block_number = IDXDeliveryBlockNumber()
+ _idx_delivery_block_number.latest_block_number = 0
+ _idx_delivery_block_number.exchange_address = (
+ ibet_security_token_dvp_contract.address
+ )
+ db.add(_idx_delivery_block_number)
+
+ db.commit()
+
+ # Transfer
+ tx = token_contract_1.functions.transferFrom(
+ issuer_address, ibet_security_token_dvp_contract.address, 40
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # CreateDelivery
+ tx = ibet_security_token_dvp_contract.functions.createDelivery(
+ token_address_1, user_address_1, 30, agent_address, "." * 1000
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ tx_hash_1, tx_receipt_1 = ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # ConfirmDelivery
+ tx = ibet_security_token_dvp_contract.functions.confirmDelivery(
+ 1
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": user_address_1,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ tx_hash_2, tx_receipt_2 = ContractUtils.send_transaction(tx, user_private_key_1)
+
+ # FinishDelivery
+ tx = ibet_security_token_dvp_contract.functions.abortDelivery(
+ 1
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": agent_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ tx_hash_3, tx_receipt_3 = ContractUtils.send_transaction(tx, agent_private_key)
+
+ # Run target process
+ block_number = await web3.eth.block_number
+ await processor.sync_new_logs()
+
+ # Assertion
+ _delivery_list = db.scalars(select(IDXDelivery)).all()
+ assert len(_delivery_list) == 1
+ _delivery = _delivery_list[0]
+ assert _delivery.id == 1
+ assert _delivery.exchange_address == ibet_security_token_dvp_contract.address
+ assert _delivery.token_address == token_address_1
+ assert _delivery.buyer_address == user_address_1
+ assert _delivery.seller_address == issuer_address
+ assert _delivery.amount == 30
+ assert _delivery.agent_address == agent_address
+ assert _delivery.data == "." * 1000
+ block = await web3.eth.get_block(tx_receipt_1["blockNumber"])
+ assert _delivery.create_blocktimestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
+ assert _delivery.create_transaction_hash == tx_hash_1
+ assert _delivery.cancel_blocktimestamp is None
+ assert _delivery.cancel_transaction_hash is None
+ block = await web3.eth.get_block(tx_receipt_2["blockNumber"])
+ assert _delivery.confirm_blocktimestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
+ assert _delivery.confirm_transaction_hash == tx_hash_2
+ assert _delivery.finish_blocktimestamp is None
+ assert _delivery.finish_transaction_hash is None
+ block = await web3.eth.get_block(tx_receipt_3["blockNumber"])
+ assert _delivery.abort_blocktimestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
+ assert _delivery.abort_transaction_hash == tx_hash_3
+ assert _delivery.confirmed is True
+ assert _delivery.valid is False
+ assert _delivery.status == DeliveryStatus.DELIVERY_ABORTED
+
+ _idx_delivery_block_number = db.scalars(
+ select(IDXDeliveryBlockNumber).limit(1)
+ ).first()
+ assert (
+ _idx_delivery_block_number.exchange_address
+ == ibet_security_token_dvp_contract.address
+ )
+ assert _idx_delivery_block_number.latest_block_number == block_number
+
+ assert (
+ caplog.record_tuples.count(
+ (
+ LOG.name,
+ logging.INFO,
+ f"Syncing from=1, to={block_number}, exchange={ibet_security_token_dvp_contract.address}",
+ )
+ )
+ == 1
+ )
+
+ #
+ # Multi Exchange
+ @pytest.mark.asyncio
+ async def test_normal_3(
+ self,
+ processor,
+ db,
+ personal_info_contract,
+ ibet_security_token_escrow_contract,
+ ibet_security_token_dvp_contract,
+ caplog: pytest.LogCaptureFixture,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ agent_address = user_3["address"]
+ agent_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = user_1["keyfile_json"]
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ # Prepare data : Token
+ token_contract_1 = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_escrow_contract.address,
+ )
+ token_address_1 = token_contract_1.address
+ token_1 = Token()
+ token_1.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_1.token_address = token_address_1
+ token_1.issuer_address = issuer_address
+ token_1.abi = token_contract_1.abi
+ token_1.tx_hash = "tx_hash"
+ token_1.version = TokenVersion.V_24_06
+ db.add(token_1)
+
+ # Prepare data : Token
+ token_contract_2 = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ )
+ token_address_2 = token_contract_2.address
+ token_2 = Token()
+ token_2.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_2.token_address = token_address_2
+ token_2.issuer_address = issuer_address
+ token_2.abi = token_contract_2.abi
+ token_2.tx_hash = "tx_hash"
+ token_2.version = TokenVersion.V_24_06
+ db.add(token_2)
+
+ # Prepare data : BlockNumber
+ _idx_delivery_block_number = IDXDeliveryBlockNumber()
+ _idx_delivery_block_number.latest_block_number = 0
+ _idx_delivery_block_number.exchange_address = (
+ ibet_security_token_dvp_contract.address
+ )
+ db.add(_idx_delivery_block_number)
+
+ db.commit()
+
+ # Transfer
+ tx = token_contract_2.functions.transferFrom(
+ issuer_address, ibet_security_token_dvp_contract.address, 40
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # CreateDelivery
+ tx = ibet_security_token_dvp_contract.functions.createDelivery(
+ token_address_2, user_address_1, 30, agent_address, "." * 1000
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ tx_hash_1, tx_receipt_1 = ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # ConfirmDelivery
+ tx = ibet_security_token_dvp_contract.functions.confirmDelivery(
+ 1
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": user_address_1,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ tx_hash_2, tx_receipt_2 = ContractUtils.send_transaction(tx, user_private_key_1)
+
+ # FinishDelivery
+ tx = ibet_security_token_dvp_contract.functions.abortDelivery(
+ 1
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": agent_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ tx_hash_3, tx_receipt_3 = ContractUtils.send_transaction(tx, agent_private_key)
+
+ # Run target process
+ block_number = await web3.eth.block_number
+ await processor.sync_new_logs()
+
+ # Assertion
+ _delivery_list = db.scalars(select(IDXDelivery)).all()
+ assert len(_delivery_list) == 1
+ _delivery = _delivery_list[0]
+ assert _delivery.id == 1
+ assert _delivery.exchange_address == ibet_security_token_dvp_contract.address
+ assert _delivery.token_address == token_address_2
+ assert _delivery.buyer_address == user_address_1
+ assert _delivery.seller_address == issuer_address
+ assert _delivery.amount == 30
+ assert _delivery.agent_address == agent_address
+ assert _delivery.data == "." * 1000
+ block = await web3.eth.get_block(tx_receipt_1["blockNumber"])
+ assert _delivery.create_blocktimestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
+ assert _delivery.create_transaction_hash == tx_hash_1
+ assert _delivery.cancel_blocktimestamp is None
+ assert _delivery.cancel_transaction_hash is None
+ block = await web3.eth.get_block(tx_receipt_2["blockNumber"])
+ assert _delivery.confirm_blocktimestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
+ assert _delivery.confirm_transaction_hash == tx_hash_2
+ assert _delivery.finish_blocktimestamp is None
+ assert _delivery.finish_transaction_hash is None
+ block = await web3.eth.get_block(tx_receipt_3["blockNumber"])
+ assert _delivery.abort_blocktimestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
+ assert _delivery.abort_transaction_hash == tx_hash_3
+ assert _delivery.confirmed is True
+ assert _delivery.valid is False
+ assert _delivery.status == DeliveryStatus.DELIVERY_ABORTED
+
+ _idx_delivery_block_number = db.scalars(
+ select(IDXDeliveryBlockNumber).where(
+ IDXDeliveryBlockNumber.exchange_address
+ == ibet_security_token_escrow_contract.address
+ )
+ ).first()
+ assert _idx_delivery_block_number.latest_block_number == block_number
+ _idx_delivery_block_number = db.scalars(
+ select(IDXDeliveryBlockNumber).where(
+ IDXDeliveryBlockNumber.exchange_address
+ == ibet_security_token_dvp_contract.address
+ )
+ ).first()
+ assert _idx_delivery_block_number.latest_block_number == block_number
+
+ assert (
+ caplog.record_tuples.count(
+ (
+ LOG.name,
+ logging.INFO,
+ f"Syncing from=1, to={block_number}, exchange={ibet_security_token_escrow_contract.address}",
+ )
+ )
+ == 1
+ )
+
+ assert (
+ caplog.record_tuples.count(
+ (
+ LOG.name,
+ logging.INFO,
+ f"Syncing from=1, to={block_number}, exchange={ibet_security_token_dvp_contract.address}",
+ )
+ )
+ == 1
+ )
+
+ #
+ # If block number processed in batch is equal or greater than current block number,
+ # batch will output a log "skip process".
+ @mock.patch("web3.eth.Eth.block_number", 100)
+ @pytest.mark.asyncio
+ async def test_normal_4(
+ self,
+ processor: Processor,
+ db: Session,
+ personal_info_contract,
+ ibet_security_token_dvp_contract,
+ caplog: pytest.LogCaptureFixture,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_private_key_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ user_address_2 = user_3["address"]
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = user_1["keyfile_json"]
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ # Prepare data : Token
+ token_contract_1 = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ )
+ token_address_1 = token_contract_1.address
+ token_1 = Token()
+ token_1.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_1.token_address = token_address_1
+ token_1.issuer_address = issuer_address
+ token_1.abi = token_contract_1.abi
+ token_1.tx_hash = "tx_hash"
+ token_1.version = TokenVersion.V_24_06
+ db.add(token_1)
+
+ # Prepare data : Token(processing token)
+ token_2 = Token()
+ token_2.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_2.token_address = "test1"
+ token_2.issuer_address = issuer_address
+ token_2.abi = "abi"
+ token_2.tx_hash = "tx_hash"
+ token_2.token_status = 0
+ token_2.version = TokenVersion.V_24_06
+ db.add(token_2)
+
+ # Prepare data : BlockNumber
+ _idx_delivery_block_number = IDXDeliveryBlockNumber()
+ _idx_delivery_block_number.latest_block_number = 100
+ _idx_delivery_block_number.exchange_address = (
+ ibet_security_token_dvp_contract.address
+ )
+ db.add(_idx_delivery_block_number)
+
+ db.commit()
+
+ await processor.sync_new_logs()
+ assert (
+ caplog.record_tuples.count((LOG.name, logging.DEBUG, "skip process")) == 1
+ )
+
+ #
+ # Newly tokens added
+ @pytest.mark.asyncio
+ async def test_normal_6(
+ self,
+ processor: Processor,
+ db: Session,
+ personal_info_contract,
+ ibet_security_token_dvp_contract,
+ ibet_security_token_escrow_contract,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = user_1["keyfile_json"]
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ # Issuer issues bond token.
+ token_contract1 = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_escrow_contract.address,
+ )
+ token_address_1 = token_contract1.address
+ token_1 = Token()
+ token_1.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_1.token_address = token_address_1
+ token_1.issuer_address = issuer_address
+ token_1.abi = token_contract1.abi
+ token_1.tx_hash = "tx_hash"
+ token_1.version = TokenVersion.V_24_06
+ db.add(token_1)
+
+ db.commit()
+
+ # Run target process
+ await processor.sync_new_logs()
+
+ # Assertion
+ assert len(processor.token_list) == 1
+ assert len(processor.exchange_list) == 1
+
+ # Prepare additional token
+ token_contract2 = await deploy_share_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ transfer_approval_required=False,
+ )
+ token_address_2 = token_contract2.address
+ token_2 = Token()
+ token_2.type = TokenType.IBET_SHARE.value
+ token_2.token_address = token_address_2
+ token_2.issuer_address = issuer_address
+ token_2.abi = token_contract2.abi
+ token_2.tx_hash = "tx_hash"
+ token_2.version = TokenVersion.V_24_06
+ db.add(token_2)
+
+ db.commit()
+
+ # Run target process
+ await processor.sync_new_logs()
+
+ # Assertion
+ # newly issued token is loaded properly
+ assert len(processor.token_list) == 2
+ assert len(processor.exchange_list) == 2
+
+ ###########################################################################
+ # Error Case
+ ###########################################################################
+
+ #
+ # If each error occurs, batch will output logs and continue next sync.
+ @pytest.mark.asyncio
+ async def test_error_1(
+ self,
+ main_func,
+ db: Session,
+ personal_info_contract,
+ caplog: pytest.LogCaptureFixture,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = user_1["keyfile_json"]
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ # Prepare data : Token
+ token_contract = await deploy_bond_token_contract(
+ issuer_address, issuer_private_key, personal_info_contract.address
+ )
+ token_address = token_contract.address
+ token = Token()
+ token.type = TokenType.IBET_STRAIGHT_BOND.value
+ token.token_address = token_address
+ token.issuer_address = issuer_address
+ token.abi = token_contract.abi
+ token.tx_hash = "tx_hash"
+ token.version = TokenVersion.V_24_06
+ db.add(token)
+
+ db.commit()
+
+ # Run mainloop once and fail with web3 utils error
+ with patch("batch.indexer_delivery.INDEXER_SYNC_INTERVAL", None), patch.object(
+ AsyncWeb3Wrapper().eth, "contract", side_effect=ServiceUnavailableError()
+ ), pytest.raises(TypeError):
+ await main_func()
+ assert 1 == caplog.record_tuples.count(
+ (LOG.name, logging.WARNING, "An external service was unavailable")
+ )
+ caplog.clear()
+
+ # Run mainloop once and fail with sqlalchemy Error
+ with patch("batch.indexer_delivery.INDEXER_SYNC_INTERVAL", None), patch.object(
+ AsyncSession, "commit", side_effect=SQLAlchemyError(code="dbapi")
+ ), pytest.raises(TypeError):
+ await main_func()
+ assert "A database error has occurred: code=dbapi" in caplog.text
+ caplog.clear()
diff --git a/tests/test_batch_indexer_e2e_messaging.py b/tests/batch/test_indexer_e2e_messaging.py
similarity index 87%
rename from tests/test_batch_indexer_e2e_messaging.py
rename to tests/batch/test_indexer_e2e_messaging.py
index 129e2a34..eef12eb7 100644
--- a/tests/test_batch_indexer_e2e_messaging.py
+++ b/tests/batch/test_indexer_e2e_messaging.py
@@ -20,8 +20,7 @@
import base64
import json
import os
-import time
-from datetime import datetime
+from datetime import UTC, datetime
import pytest
from Crypto import Random
@@ -175,18 +174,6 @@ async def test_normal_2_1(self, processor, db, e2e_messaging_contract):
_e2e_account.is_deleted = False
db.add(_e2e_account)
- # Prepare data : E2EMessagingAccountRsaKey
- _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
- _e2e_account_rsa_key.account_address = user_address_1
- _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
- _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
- _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
- db.add(_e2e_account_rsa_key)
- time.sleep(1)
-
- db.commit()
-
# Send Message
_type = "test_type"
message = {
@@ -194,6 +181,7 @@ async def test_normal_2_1(self, processor, db, e2e_messaging_contract):
"address": "東京都1",
}
message_message_str = json.dumps(message)
+
sending_tx_hash, sending_tx_receipt = await E2EMessaging(
e2e_messaging_contract.address
).send_message_external(
@@ -205,7 +193,22 @@ async def test_normal_2_1(self, processor, db, e2e_messaging_contract):
user_private_key_2,
)
sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
- sending_block_timestamp = datetime.utcfromtimestamp(sending_block["timestamp"])
+ sending_block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"], UTC
+ ).replace(tzinfo=None)
+
+ # Prepare data : E2EMessagingAccountRsaKey
+ _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
+ _e2e_account_rsa_key.account_address = user_address_1
+ _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
+ _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
+ _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"] - 1, UTC
+ ).replace(tzinfo=None)
+ db.add(_e2e_account_rsa_key)
+
+ db.commit()
# Run target process
block_number = web3.eth.block_number
@@ -250,15 +253,39 @@ async def test_normal_2_2(self, processor, db, e2e_messaging_contract):
_e2e_account.is_deleted = False
db.add(_e2e_account)
+ # Send Message
+ _type = "test_type"
+ message = {
+ "name": "テスト太郎1",
+ "address": "東京都1",
+ }
+ message_message_str = json.dumps(message)
+
+ sending_tx_hash, sending_tx_receipt = await E2EMessaging(
+ e2e_messaging_contract.address
+ ).send_message_external(
+ user_address_1,
+ _type,
+ message_message_str,
+ self.rsa_public_key,
+ user_address_2,
+ user_private_key_2,
+ )
+ sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
+ sending_block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"], UTC
+ ).replace(tzinfo=None)
+
# Prepare data : E2EMessagingAccountRsaKey
_e2e_account_rsa_key = E2EMessagingAccountRsaKey()
_e2e_account_rsa_key.account_address = user_address_1
_e2e_account_rsa_key.rsa_private_key = "test1"
_e2e_account_rsa_key.rsa_public_key = "test1"
_e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"] - 3, UTC
+ ).replace(tzinfo=None)
db.add(_e2e_account_rsa_key)
- time.sleep(1)
# Prepare data : E2EMessagingAccountRsaKey
_e2e_account_rsa_key = E2EMessagingAccountRsaKey()
@@ -266,9 +293,10 @@ async def test_normal_2_2(self, processor, db, e2e_messaging_contract):
_e2e_account_rsa_key.rsa_private_key = "test2"
_e2e_account_rsa_key.rsa_public_key = "test2"
_e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"] - 2, UTC
+ ).replace(tzinfo=None)
db.add(_e2e_account_rsa_key)
- time.sleep(1)
# Prepare data : E2EMessagingAccountRsaKey
_e2e_account_rsa_key = E2EMessagingAccountRsaKey()
@@ -276,29 +304,10 @@ async def test_normal_2_2(self, processor, db, e2e_messaging_contract):
_e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
_e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
_e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"] - 1, UTC
+ ).replace(tzinfo=None)
db.add(_e2e_account_rsa_key)
- time.sleep(1)
-
- # Send Message
- _type = "test_type"
- message = {
- "name": "テスト太郎1",
- "address": "東京都1",
- }
- message_message_str = json.dumps(message)
- sending_tx_hash, sending_tx_receipt = await E2EMessaging(
- e2e_messaging_contract.address
- ).send_message_external(
- user_address_1,
- _type,
- message_message_str,
- self.rsa_public_key,
- user_address_2,
- user_private_key_2,
- )
- sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
- sending_block_timestamp = datetime.utcfromtimestamp(sending_block["timestamp"])
# Prepare data : E2EMessagingAccountRsaKey
_e2e_account_rsa_key = E2EMessagingAccountRsaKey()
@@ -306,9 +315,10 @@ async def test_normal_2_2(self, processor, db, e2e_messaging_contract):
_e2e_account_rsa_key.rsa_private_key = "test3"
_e2e_account_rsa_key.rsa_public_key = "test3"
_e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"] + 1, UTC
+ ).replace(tzinfo=None)
db.add(_e2e_account_rsa_key)
- time.sleep(1)
# Prepare data : E2EMessagingAccountRsaKey
_e2e_account_rsa_key = E2EMessagingAccountRsaKey()
@@ -316,10 +326,10 @@ async def test_normal_2_2(self, processor, db, e2e_messaging_contract):
_e2e_account_rsa_key.rsa_private_key = "test4"
_e2e_account_rsa_key.rsa_public_key = "test4"
_e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"] + 2, UTC
+ ).replace(tzinfo=None)
db.add(_e2e_account_rsa_key)
- time.sleep(1)
-
db.commit()
# Run target process
@@ -366,34 +376,12 @@ async def test_normal_3(self, processor, db, e2e_messaging_contract):
_e2e_account.is_deleted = False
db.add(_e2e_account)
- # Prepare data : E2EMessagingAccountRsaKey
- _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
- _e2e_account_rsa_key.account_address = user_address_1
- _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
- _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
- _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
- db.add(_e2e_account_rsa_key)
- time.sleep(1)
-
# Prepare data : E2EMessagingAccount
_e2e_account = E2EMessagingAccount()
_e2e_account.account_address = user_address_2
_e2e_account.is_deleted = False
db.add(_e2e_account)
- # Prepare data : E2EMessagingAccountRsaKey
- _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
- _e2e_account_rsa_key.account_address = user_address_2
- _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
- _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
- _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
- db.add(_e2e_account_rsa_key)
- time.sleep(1)
-
- db.commit()
-
# Send Message(user3 -> user1)
_type_1 = "test_type1"
message = {
@@ -401,6 +389,7 @@ async def test_normal_3(self, processor, db, e2e_messaging_contract):
"address": "東京都1",
}
message_message_str_1 = json.dumps(message)
+
sending_tx_hash_1, sending_tx_receipt = await E2EMessaging(
e2e_messaging_contract.address
).send_message_external(
@@ -411,15 +400,16 @@ async def test_normal_3(self, processor, db, e2e_messaging_contract):
user_address_3,
user_private_key_3,
)
- sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
- sending_block_timestamp_1 = datetime.utcfromtimestamp(
- sending_block["timestamp"]
- )
+ sending_block_1 = web3.eth.get_block(sending_tx_receipt["blockNumber"])
+ sending_block_timestamp_1 = datetime.fromtimestamp(
+ sending_block_1["timestamp"], UTC
+ ).replace(tzinfo=None)
# Send Message(user3 -> user2)
_type_2 = "test_type2"
message = ["テスト太郎2", "東京都2"]
message_message_str_2 = json.dumps(message)
+
sending_tx_hash_2, sending_tx_receipt = await E2EMessaging(
e2e_messaging_contract.address
).send_message_external(
@@ -430,14 +420,15 @@ async def test_normal_3(self, processor, db, e2e_messaging_contract):
user_address_3,
user_private_key_3,
)
- sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
- sending_block_timestamp_2 = datetime.utcfromtimestamp(
- sending_block["timestamp"]
- )
+ sending_block_2 = web3.eth.get_block(sending_tx_receipt["blockNumber"])
+ sending_block_timestamp_2 = datetime.fromtimestamp(
+ sending_block_2["timestamp"], UTC
+ ).replace(tzinfo=None)
# Send Message(user3 -> user1)
_type_3 = "test_type3"
message_message_str_3 = "テスト太郎1,東京都1"
+
sending_tx_hash_3, sending_tx_receipt = await E2EMessaging(
e2e_messaging_contract.address
).send_message_external(
@@ -448,14 +439,15 @@ async def test_normal_3(self, processor, db, e2e_messaging_contract):
user_address_3,
user_private_key_3,
)
- sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
- sending_block_timestamp_3 = datetime.utcfromtimestamp(
- sending_block["timestamp"]
- )
+ sending_block_3 = web3.eth.get_block(sending_tx_receipt["blockNumber"])
+ sending_block_timestamp_3 = datetime.fromtimestamp(
+ sending_block_3["timestamp"], UTC
+ ).replace(tzinfo=None)
# Send Message(user3 -> user2)
_type_4 = "a" * 50
message_message_str_4 = "a" * 5000
+
sending_tx_hash_4, sending_tx_receipt = await E2EMessaging(
e2e_messaging_contract.address
).send_message_external(
@@ -466,10 +458,34 @@ async def test_normal_3(self, processor, db, e2e_messaging_contract):
user_address_3,
user_private_key_3,
)
- sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
- sending_block_timestamp_4 = datetime.utcfromtimestamp(
- sending_block["timestamp"]
- )
+ sending_block_4 = web3.eth.get_block(sending_tx_receipt["blockNumber"])
+ sending_block_timestamp_4 = datetime.fromtimestamp(
+ sending_block_4["timestamp"], UTC
+ ).replace(tzinfo=None)
+
+ # Prepare data : E2EMessagingAccountRsaKey
+ _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
+ _e2e_account_rsa_key.account_address = user_address_1
+ _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
+ _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
+ _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block_1["timestamp"] - 2, UTC
+ ).replace(tzinfo=None)
+ db.add(_e2e_account_rsa_key)
+
+ # Prepare data : E2EMessagingAccountRsaKey
+ _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
+ _e2e_account_rsa_key.account_address = user_address_2
+ _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
+ _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
+ _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block_1["timestamp"] - 1, UTC
+ ).replace(tzinfo=None)
+ db.add(_e2e_account_rsa_key)
+
+ db.commit()
# Run target process
block_number = web3.eth.block_number
@@ -542,18 +558,6 @@ async def test_normal_4(self, processor, db, e2e_messaging_contract):
_e2e_account.is_deleted = False
db.add(_e2e_account)
- # Prepare data : E2EMessagingAccountRsaKey
- _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
- _e2e_account_rsa_key.account_address = user_address_1
- _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
- _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
- _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
- db.add(_e2e_account_rsa_key)
- time.sleep(1)
-
- db.commit()
-
# Send Message
_type = "test_type"
message = {
@@ -561,7 +565,10 @@ async def test_normal_4(self, processor, db, e2e_messaging_contract):
"address": "東京都1",
}
message_message_str = json.dumps(message)
- await E2EMessaging(e2e_messaging_contract.address).send_message_external(
+
+ sending_tx_hash, sending_tx_receipt = await E2EMessaging(
+ e2e_messaging_contract.address
+ ).send_message_external(
user_address_3, # not target
_type,
message_message_str,
@@ -569,6 +576,20 @@ async def test_normal_4(self, processor, db, e2e_messaging_contract):
user_address_2,
user_private_key_2,
)
+ sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
+
+ # Prepare data : E2EMessagingAccountRsaKey
+ _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
+ _e2e_account_rsa_key.account_address = user_address_1
+ _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
+ _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
+ _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"] - 1, UTC
+ ).replace(tzinfo=None)
+ db.add(_e2e_account_rsa_key)
+
+ db.commit()
# Run target process
block_number = web3.eth.block_number
@@ -608,24 +629,26 @@ async def test_error_1_1(self, processor, db, e2e_messaging_contract):
_e2e_account.is_deleted = False
db.add(_e2e_account)
+ # Send Message
+ message = "test"
+ sending_tx_hash, sending_tx_receipt = await E2EMessaging(
+ e2e_messaging_contract.address
+ ).send_message(user_address_1, message, user_address_2, user_private_key_2)
+ sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
+
# Prepare data : E2EMessagingAccountRsaKey
_e2e_account_rsa_key = E2EMessagingAccountRsaKey()
_e2e_account_rsa_key.account_address = user_address_1
_e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
_e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
_e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"] - 1, UTC
+ ).replace(tzinfo=None)
db.add(_e2e_account_rsa_key)
- time.sleep(1)
db.commit()
- # Send Message
- message = "test"
- await E2EMessaging(e2e_messaging_contract.address).send_message(
- user_address_1, message, user_address_2, user_private_key_2
- )
-
# Run target process
block_number = web3.eth.block_number
await processor.process()
@@ -660,18 +683,6 @@ async def test_error_1_2(self, processor, db, e2e_messaging_contract):
_e2e_account.is_deleted = False
db.add(_e2e_account)
- # Prepare data : E2EMessagingAccountRsaKey
- _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
- _e2e_account_rsa_key.account_address = user_address_1
- _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
- _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
- _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
- db.add(_e2e_account_rsa_key)
- time.sleep(1)
-
- db.commit()
-
# Send Message
aes_key = os.urandom(32)
aes_iv = os.urandom(16)
@@ -691,9 +702,23 @@ async def test_error_1_2(self, processor, db, e2e_messaging_contract):
}
}
)
- await E2EMessaging(e2e_messaging_contract.address).send_message(
- user_address_1, message, user_address_2, user_private_key_2
- )
+ sending_tx_hash, sending_tx_receipt = await E2EMessaging(
+ e2e_messaging_contract.address
+ ).send_message(user_address_1, message, user_address_2, user_private_key_2)
+ sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
+
+ # Prepare data : E2EMessagingAccountRsaKey
+ _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
+ _e2e_account_rsa_key.account_address = user_address_1
+ _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
+ _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
+ _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"] - 1, UTC
+ ).replace(tzinfo=None)
+ db.add(_e2e_account_rsa_key)
+
+ db.commit()
# Run target process
block_number = web3.eth.block_number
@@ -729,28 +754,30 @@ async def test_error_1_3(self, processor, db, e2e_messaging_contract):
_e2e_account.is_deleted = False
db.add(_e2e_account)
+ # Send Message
+ message = json.dumps(
+ {
+ "type": "test_type",
+ }
+ )
+ sending_tx_hash, sending_tx_receipt = await E2EMessaging(
+ e2e_messaging_contract.address
+ ).send_message(user_address_1, message, user_address_2, user_private_key_2)
+ sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
+
# Prepare data : E2EMessagingAccountRsaKey
_e2e_account_rsa_key = E2EMessagingAccountRsaKey()
_e2e_account_rsa_key.account_address = user_address_1
_e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
_e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
_e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"] - 1, UTC
+ ).replace(tzinfo=None)
db.add(_e2e_account_rsa_key)
- time.sleep(1)
db.commit()
- # Send Message
- message = json.dumps(
- {
- "type": "test_type",
- }
- )
- await E2EMessaging(e2e_messaging_contract.address).send_message(
- user_address_1, message, user_address_2, user_private_key_2
- )
-
# Run target process
block_number = web3.eth.block_number
await processor.process()
@@ -785,18 +812,6 @@ async def test_error_1_4(self, processor, db, e2e_messaging_contract):
_e2e_account.is_deleted = False
db.add(_e2e_account)
- # Prepare data : E2EMessagingAccountRsaKey
- _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
- _e2e_account_rsa_key.account_address = user_address_1
- _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
- _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
- _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
- db.add(_e2e_account_rsa_key)
- time.sleep(1)
-
- db.commit()
-
# Send Message
aes_key = os.urandom(32)
aes_iv = os.urandom(16)
@@ -814,9 +829,23 @@ async def test_error_1_4(self, processor, db, e2e_messaging_contract):
"text": {"cipher_key": cipher_key, "message": encrypted_message},
}
)
- await E2EMessaging(e2e_messaging_contract.address).send_message(
- user_address_1, message, user_address_2, user_private_key_2
- )
+ sending_tx_hash, sending_tx_receipt = await E2EMessaging(
+ e2e_messaging_contract.address
+ ).send_message(user_address_1, message, user_address_2, user_private_key_2)
+ sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
+
+ # Prepare data : E2EMessagingAccountRsaKey
+ _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
+ _e2e_account_rsa_key.account_address = user_address_1
+ _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
+ _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
+ _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"] - 1, UTC
+ ).replace(tzinfo=None)
+ db.add(_e2e_account_rsa_key)
+
+ db.commit()
# Run target process
block_number = web3.eth.block_number
@@ -852,18 +881,6 @@ async def test_error_1_5(self, processor, db, e2e_messaging_contract):
_e2e_account.is_deleted = False
db.add(_e2e_account)
- # Prepare data : E2EMessagingAccountRsaKey
- _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
- _e2e_account_rsa_key.account_address = user_address_1
- _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
- _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
- _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
- db.add(_e2e_account_rsa_key)
- time.sleep(1)
-
- db.commit()
-
# Send Message
aes_key = os.urandom(32)
aes_iv = os.urandom(16)
@@ -880,9 +897,23 @@ async def test_error_1_5(self, processor, db, e2e_messaging_contract):
},
}
)
- await E2EMessaging(e2e_messaging_contract.address).send_message(
- user_address_1, message, user_address_2, user_private_key_2
- )
+ sending_tx_hash, sending_tx_receipt = await E2EMessaging(
+ e2e_messaging_contract.address
+ ).send_message(user_address_1, message, user_address_2, user_private_key_2)
+ sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
+
+ # Prepare data : E2EMessagingAccountRsaKey
+ _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
+ _e2e_account_rsa_key.account_address = user_address_1
+ _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
+ _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
+ _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"] - 1, UTC
+ ).replace(tzinfo=None)
+ db.add(_e2e_account_rsa_key)
+
+ db.commit()
# Run target process
block_number = web3.eth.block_number
@@ -918,16 +949,6 @@ async def test_error_1_6(self, processor, db, e2e_messaging_contract):
_e2e_account.is_deleted = False
db.add(_e2e_account)
- # Prepare data : E2EMessagingAccountRsaKey
- _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
- _e2e_account_rsa_key.account_address = user_address_1
- _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
- _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
- _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
- db.add(_e2e_account_rsa_key)
- time.sleep(1)
-
db.commit()
# Send Message
@@ -943,9 +964,21 @@ async def test_error_1_6(self, processor, db, e2e_messaging_contract):
},
}
)
- await E2EMessaging(e2e_messaging_contract.address).send_message(
- user_address_1, message, user_address_2, user_private_key_2
- )
+ sending_tx_hash, sending_tx_receipt = await E2EMessaging(
+ e2e_messaging_contract.address
+ ).send_message(user_address_1, message, user_address_2, user_private_key_2)
+ sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
+
+ # Prepare data : E2EMessagingAccountRsaKey
+ _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
+ _e2e_account_rsa_key.account_address = user_address_1
+ _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
+ _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
+ _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"] - 1, UTC
+ ).replace(tzinfo=None)
+ db.add(_e2e_account_rsa_key)
# Run target process
block_number = web3.eth.block_number
@@ -981,18 +1014,6 @@ async def test_error_1_7(self, processor, db, e2e_messaging_contract):
_e2e_account.is_deleted = False
db.add(_e2e_account)
- # Prepare data : E2EMessagingAccountRsaKey
- _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
- _e2e_account_rsa_key.account_address = user_address_1
- _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
- _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
- _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
- db.add(_e2e_account_rsa_key)
- time.sleep(1)
-
- db.commit()
-
# Send Message
aes_key = os.urandom(32)
aes_iv = os.urandom(16)
@@ -1010,9 +1031,23 @@ async def test_error_1_7(self, processor, db, e2e_messaging_contract):
"text": {"cipher_key": cipher_key, "message": encrypted_message},
}
)
- await E2EMessaging(e2e_messaging_contract.address).send_message(
- user_address_1, message, user_address_2, user_private_key_2
- )
+ sending_tx_hash, sending_tx_receipt = await E2EMessaging(
+ e2e_messaging_contract.address
+ ).send_message(user_address_1, message, user_address_2, user_private_key_2)
+ sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
+
+ # Prepare data : E2EMessagingAccountRsaKey
+ _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
+ _e2e_account_rsa_key.account_address = user_address_1
+ _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
+ _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
+ _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"] - 1, UTC
+ ).replace(tzinfo=None)
+ db.add(_e2e_account_rsa_key)
+
+ db.commit()
# Run target process
block_number = web3.eth.block_number
@@ -1054,7 +1089,10 @@ async def test_error_2(self, processor, db, e2e_messaging_contract):
"address": "東京都1",
}
message_message_str = json.dumps(message)
- await E2EMessaging(e2e_messaging_contract.address).send_message_external(
+
+ sending_tx_hash, sending_tx_receipt = await E2EMessaging(
+ e2e_messaging_contract.address
+ ).send_message_external(
user_address_1,
_type,
message_message_str,
@@ -1062,7 +1100,7 @@ async def test_error_2(self, processor, db, e2e_messaging_contract):
user_address_2,
user_private_key_2,
)
- time.sleep(1)
+ sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
# Prepare data : E2EMessagingAccountRsaKey
_e2e_account_rsa_key = E2EMessagingAccountRsaKey()
@@ -1070,8 +1108,10 @@ async def test_error_2(self, processor, db, e2e_messaging_contract):
_e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
_e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
_e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = (
- datetime.utcnow()
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"] + 1, UTC
+ ).replace(
+ tzinfo=None
) # Registry after send message
db.add(_e2e_account_rsa_key)
@@ -1111,18 +1151,6 @@ async def test_error_3_1(self, processor, db, e2e_messaging_contract):
_e2e_account.is_deleted = False
db.add(_e2e_account)
- # Prepare data : E2EMessagingAccountRsaKey
- _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
- _e2e_account_rsa_key.account_address = user_address_1
- _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
- _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
- _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
- db.add(_e2e_account_rsa_key)
- time.sleep(1)
-
- db.commit()
-
# Send Message
aes_key = os.urandom(32)
aes_iv = os.urandom(16)
@@ -1137,9 +1165,23 @@ async def test_error_3_1(self, processor, db, e2e_messaging_contract):
"text": {"cipher_key": "cipher_key", "message": encrypted_message},
}
)
- await E2EMessaging(e2e_messaging_contract.address).send_message(
- user_address_1, message, user_address_2, user_private_key_2
- )
+ sending_tx_hash, sending_tx_receipt = await E2EMessaging(
+ e2e_messaging_contract.address
+ ).send_message(user_address_1, message, user_address_2, user_private_key_2)
+ sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
+
+ # Prepare data : E2EMessagingAccountRsaKey
+ _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
+ _e2e_account_rsa_key.account_address = user_address_1
+ _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
+ _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
+ _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"] - 1, UTC
+ ).replace(tzinfo=None)
+ db.add(_e2e_account_rsa_key)
+
+ db.commit()
# Run target process
block_number = web3.eth.block_number
@@ -1175,18 +1217,6 @@ async def test_error_3_2(self, processor, db, e2e_messaging_contract):
_e2e_account.is_deleted = False
db.add(_e2e_account)
- # Prepare data : E2EMessagingAccountRsaKey
- _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
- _e2e_account_rsa_key.account_address = user_address_1
- _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
- _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
- _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
- db.add(_e2e_account_rsa_key)
- time.sleep(1)
-
- db.commit()
-
# Send Message
aes_key = os.urandom(32)
aes_iv = os.urandom(16)
@@ -1202,9 +1232,23 @@ async def test_error_3_2(self, processor, db, e2e_messaging_contract):
"text": {"cipher_key": cipher_key, "message": encrypted_message},
}
)
- await E2EMessaging(e2e_messaging_contract.address).send_message(
- user_address_1, message, user_address_2, user_private_key_2
- )
+ sending_tx_hash, sending_tx_receipt = await E2EMessaging(
+ e2e_messaging_contract.address
+ ).send_message(user_address_1, message, user_address_2, user_private_key_2)
+ sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
+
+ # Prepare data : E2EMessagingAccountRsaKey
+ _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
+ _e2e_account_rsa_key.account_address = user_address_1
+ _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
+ _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
+ _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"] - 1, UTC
+ ).replace(tzinfo=None)
+ db.add(_e2e_account_rsa_key)
+
+ db.commit()
# Run target process
block_number = web3.eth.block_number
@@ -1240,18 +1284,6 @@ async def test_error_3_3(self, processor, db, e2e_messaging_contract):
_e2e_account.is_deleted = False
db.add(_e2e_account)
- # Prepare data : E2EMessagingAccountRsaKey
- _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
- _e2e_account_rsa_key.account_address = user_address_1
- _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
- _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
- _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
- db.add(_e2e_account_rsa_key)
- time.sleep(1)
-
- db.commit()
-
# Send Message
random_func = Random.new().read
rsa = RSA.generate(4096, random_func)
@@ -1272,9 +1304,23 @@ async def test_error_3_3(self, processor, db, e2e_messaging_contract):
"text": {"cipher_key": cipher_key, "message": encrypted_message},
}
)
- await E2EMessaging(e2e_messaging_contract.address).send_message(
- user_address_1, message, user_address_2, user_private_key_2
- )
+ sending_tx_hash, sending_tx_receipt = await E2EMessaging(
+ e2e_messaging_contract.address
+ ).send_message(user_address_1, message, user_address_2, user_private_key_2)
+ sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
+
+ # Prepare data : E2EMessagingAccountRsaKey
+ _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
+ _e2e_account_rsa_key.account_address = user_address_1
+ _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
+ _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
+ _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"] - 1, UTC
+ ).replace(tzinfo=None)
+ db.add(_e2e_account_rsa_key)
+
+ db.commit()
# Run target process
block_number = web3.eth.block_number
@@ -1310,18 +1356,6 @@ async def test_error_3_4(self, processor, db, e2e_messaging_contract):
_e2e_account.is_deleted = False
db.add(_e2e_account)
- # Prepare data : E2EMessagingAccountRsaKey
- _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
- _e2e_account_rsa_key.account_address = user_address_1
- _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
- _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
- _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
- db.add(_e2e_account_rsa_key)
- time.sleep(1)
-
- db.commit()
-
# Send Message
aes_key = os.urandom(32)
rsa_key = RSA.import_key(self.rsa_public_key)
@@ -1333,9 +1367,23 @@ async def test_error_3_4(self, processor, db, e2e_messaging_contract):
"text": {"cipher_key": cipher_key, "message": "test_message"},
}
)
- await E2EMessaging(e2e_messaging_contract.address).send_message(
- user_address_1, message, user_address_2, user_private_key_2
- )
+ sending_tx_hash, sending_tx_receipt = await E2EMessaging(
+ e2e_messaging_contract.address
+ ).send_message(user_address_1, message, user_address_2, user_private_key_2)
+ sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
+
+ # Prepare data : E2EMessagingAccountRsaKey
+ _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
+ _e2e_account_rsa_key.account_address = user_address_1
+ _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
+ _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
+ _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"] - 1, UTC
+ ).replace(tzinfo=None)
+ db.add(_e2e_account_rsa_key)
+
+ db.commit()
# Run target process
block_number = web3.eth.block_number
@@ -1371,18 +1419,6 @@ async def test_error_3_5(self, processor, db, e2e_messaging_contract):
_e2e_account.is_deleted = False
db.add(_e2e_account)
- # Prepare data : E2EMessagingAccountRsaKey
- _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
- _e2e_account_rsa_key.account_address = user_address_1
- _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
- _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
- _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
- _e2e_account_rsa_key.block_timestamp = datetime.utcnow()
- db.add(_e2e_account_rsa_key)
- time.sleep(1)
-
- db.commit()
-
# Send Message
aes_key = os.urandom(32)
aes_iv = os.urandom(16)
@@ -1401,9 +1437,23 @@ async def test_error_3_5(self, processor, db, e2e_messaging_contract):
"text": {"cipher_key": cipher_key, "message": encrypted_message},
}
)
- await E2EMessaging(e2e_messaging_contract.address).send_message(
- user_address_1, message, user_address_2, user_private_key_2
- )
+ sending_tx_hash, sending_tx_receipt = await E2EMessaging(
+ e2e_messaging_contract.address
+ ).send_message(user_address_1, message, user_address_2, user_private_key_2)
+ sending_block = web3.eth.get_block(sending_tx_receipt["blockNumber"])
+
+ # Prepare data : E2EMessagingAccountRsaKey
+ _e2e_account_rsa_key = E2EMessagingAccountRsaKey()
+ _e2e_account_rsa_key.account_address = user_address_1
+ _e2e_account_rsa_key.rsa_private_key = self.rsa_private_key
+ _e2e_account_rsa_key.rsa_public_key = self.rsa_public_key
+ _e2e_account_rsa_key.rsa_passphrase = E2EEUtils.encrypt(self.rsa_passphrase)
+ _e2e_account_rsa_key.block_timestamp = datetime.fromtimestamp(
+ sending_block["timestamp"] - 1, UTC
+ ).replace(tzinfo=None)
+ db.add(_e2e_account_rsa_key)
+
+ db.commit()
# Run target process
block_number = web3.eth.block_number
diff --git a/tests/test_batch_indexer_issue_redeem.py b/tests/batch/test_indexer_issue_redeem.py
similarity index 89%
rename from tests/test_batch_indexer_issue_redeem.py
rename to tests/batch/test_indexer_issue_redeem.py
index e575166d..d60f5ec9 100644
--- a/tests/test_batch_indexer_issue_redeem.py
+++ b/tests/batch/test_indexer_issue_redeem.py
@@ -18,7 +18,7 @@
"""
import logging
-from datetime import datetime
+from datetime import UTC, datetime
from unittest import mock
from unittest.mock import patch
@@ -169,7 +169,7 @@ async def test_normal_1(self, processor, db, personal_info_contract):
token_1.abi = "abi"
token_1.tx_hash = "tx_hash"
token_1.token_status = 0
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -211,7 +211,7 @@ async def test_normal_2(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -262,7 +262,7 @@ async def test_normal_3_1(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -296,7 +296,9 @@ async def test_normal_3_1(self, processor, db, personal_info_contract):
assert event_0.target_address == issuer_address
assert event_0.amount == 40
block = web3.eth.get_block(tx_receipt_1["blockNumber"])
- assert event_0.block_timestamp == datetime.utcfromtimestamp(block["timestamp"])
+ assert event_0.block_timestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
idx_block_number = db.scalars(
select(IDXIssueRedeemBlockNumber).limit(1)
@@ -336,7 +338,7 @@ async def test_normal_3_2(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -370,7 +372,9 @@ async def test_normal_3_2(self, processor, db, personal_info_contract):
assert event_0.target_address == issuer_address
assert event_0.amount == 40
block = web3.eth.get_block(tx_receipt_1["blockNumber"])
- assert event_0.block_timestamp == datetime.utcfromtimestamp(block["timestamp"])
+ assert event_0.block_timestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
idx_block_number = db.scalars(
select(IDXIssueRedeemBlockNumber).limit(1)
@@ -410,7 +414,7 @@ async def test_normal_4_1(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -444,7 +448,9 @@ async def test_normal_4_1(self, processor, db, personal_info_contract):
assert event_0.target_address == issuer_address
assert event_0.amount == 10
block = web3.eth.get_block(tx_receipt_1["blockNumber"])
- assert event_0.block_timestamp == datetime.utcfromtimestamp(block["timestamp"])
+ assert event_0.block_timestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
idx_block_number = db.scalars(
select(IDXIssueRedeemBlockNumber).limit(1)
@@ -484,7 +490,7 @@ async def test_normal_4_2(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -518,7 +524,9 @@ async def test_normal_4_2(self, processor, db, personal_info_contract):
assert event_0.target_address == issuer_address
assert event_0.amount == 10
block = web3.eth.get_block(tx_receipt_1["blockNumber"])
- assert event_0.block_timestamp == datetime.utcfromtimestamp(block["timestamp"])
+ assert event_0.block_timestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
idx_block_number = db.scalars(
select(IDXIssueRedeemBlockNumber).limit(1)
@@ -557,7 +565,7 @@ async def test_normal_5(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -604,7 +612,9 @@ async def test_normal_5(self, processor, db, personal_info_contract):
assert event_0.target_address == issuer_address
assert event_0.amount == 10
block = web3.eth.get_block(tx_receipt_1["blockNumber"])
- assert event_0.block_timestamp == datetime.utcfromtimestamp(block["timestamp"])
+ assert event_0.block_timestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
event_1 = event_list[1]
assert event_1.id == 2
@@ -615,7 +625,9 @@ async def test_normal_5(self, processor, db, personal_info_contract):
assert event_1.target_address == issuer_address
assert event_1.amount == 20
block = web3.eth.get_block(tx_receipt_2["blockNumber"])
- assert event_1.block_timestamp == datetime.utcfromtimestamp(block["timestamp"])
+ assert event_1.block_timestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
idx_block_number = db.scalars(
select(IDXIssueRedeemBlockNumber).limit(1)
@@ -624,77 +636,11 @@ async def test_normal_5(self, processor, db, personal_info_contract):
assert idx_block_number.latest_block_number == block_number
# Normal_6
- # If DB session fails in phase sinking each event, batch outputs logs exception occurred.
- @pytest.mark.asyncio
- async def test_normal_6(
- self,
- processor: Processor,
- db: Session,
- personal_info_contract,
- caplog: pytest.LogCaptureFixture,
- ):
- user_1 = config_eth_account("user1")
- issuer_address = user_1["address"]
- issuer_private_key = decode_keyfile_json(
- raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
- )
-
- # Prepare data : Account
- account = Account()
- account.issuer_address = issuer_address
- account.keyfile = user_1["keyfile_json"]
- account.eoa_password = E2EEUtils.encrypt("password")
- db.add(account)
-
- # Prepare data : Token
- token_contract_1 = await deploy_bond_token_contract(
- address=issuer_address,
- private_key=issuer_private_key,
- personal_info_contract_address=personal_info_contract.address,
- )
-
- token_address_1 = token_contract_1.address
- token_1 = Token()
- token_1.type = TokenType.IBET_STRAIGHT_BOND.value
- token_1.token_address = token_address_1
- token_1.issuer_address = issuer_address
- token_1.abi = token_contract_1.abi
- token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
- db.add(token_1)
-
- db.commit()
-
- # issueFrom
- tx = token_contract_1.functions.issueFrom(
- issuer_address, config.ZERO_ADDRESS, 10
- ).build_transaction(
- {
- "chainId": CHAIN_ID,
- "from": issuer_address,
- "gas": TX_GAS_LIMIT,
- "gasPrice": 0,
- }
- )
- ContractUtils.send_transaction(tx, issuer_private_key)
-
- with patch.object(Session, "add", side_effect=Exception()):
- await processor.sync_new_logs()
-
- assert 1 == caplog.record_tuples.count(
- (
- LOG.name,
- logging.ERROR,
- "An exception occurred during event synchronization",
- )
- )
-
- # Normal_7
# If block number processed in batch is equal or greater than current block number,
# batch logs "skip process".
@pytest.mark.asyncio
@mock.patch("web3.eth.Eth.block_number", 100)
- async def test_normal_7(
+ async def test_normal_6(
self, processor: Processor, db: Session, caplog: pytest.LogCaptureFixture
):
_idx_position_bond_block_number = IDXIssueRedeemBlockNumber()
@@ -708,10 +654,10 @@ async def test_normal_7(
(LOG.name, logging.DEBUG, "skip process")
)
- # Normal_8
+ # Normal_7
# Newly tokens added
@pytest.mark.asyncio
- async def test_normal_8(
+ async def test_normal_7(
self, processor: Processor, db: Session, personal_info_contract
):
user_1 = config_eth_account("user1")
@@ -741,7 +687,7 @@ async def test_normal_8(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -766,7 +712,7 @@ async def test_normal_8(
token_2.issuer_address = issuer_address
token_2.abi = token_contract_2.abi
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -819,7 +765,7 @@ async def test_error_1(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
diff --git a/tests/test_batch_indexer_personal_info.py b/tests/batch/test_indexer_personal_info.py
similarity index 87%
rename from tests/test_batch_indexer_personal_info.py
rename to tests/batch/test_indexer_personal_info.py
index 81f5ae59..b06a13a0 100644
--- a/tests/test_batch_indexer_personal_info.py
+++ b/tests/batch/test_indexer_personal_info.py
@@ -41,6 +41,8 @@
Account,
IDXPersonalInfo,
IDXPersonalInfoBlockNumber,
+ IDXPersonalInfoHistory,
+ PersonalInfoEventType,
Token,
TokenType,
TokenVersion,
@@ -153,7 +155,7 @@ async def test_normal_1_1(self, processor, db, personal_info_contract):
token_1.abi = "abi"
token_1.tx_hash = "tx_hash"
token_1.token_status = 0
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -165,12 +167,16 @@ async def test_normal_1_1(self, processor, db, personal_info_contract):
# Assertion
_personal_info_list = db.scalars(select(IDXPersonalInfo)).all()
assert len(_personal_info_list) == 0
+
_idx_personal_info_block_number = db.scalars(
select(IDXPersonalInfoBlockNumber).limit(1)
).first()
assert _idx_personal_info_block_number.id == 1
assert _idx_personal_info_block_number.latest_block_number == block_number
+ _personal_info_history_list = db.scalars(select(IDXPersonalInfoHistory)).all()
+ assert len(_personal_info_history_list) == 0
+
#
# Single Token
# No event logs
@@ -206,7 +212,7 @@ async def test_normal_1_2(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(processing token)
@@ -217,7 +223,7 @@ async def test_normal_1_2(self, processor, db, personal_info_contract):
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
token_2.token_status = 0
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : BlockNumber
@@ -234,12 +240,16 @@ async def test_normal_1_2(self, processor, db, personal_info_contract):
# Assertion
_personal_info_list = db.scalars(select(IDXPersonalInfo)).all()
assert len(_personal_info_list) == 0
+
_idx_personal_info_block_number = db.scalars(
select(IDXPersonalInfoBlockNumber).limit(1)
).first()
assert _idx_personal_info_block_number.id == 1
assert _idx_personal_info_block_number.latest_block_number == block_number
+ _personal_info_history_list = db.scalars(select(IDXPersonalInfoHistory)).all()
+ assert len(_personal_info_history_list) == 0
+
#
# Single Token
# Single event logs
@@ -280,7 +290,7 @@ async def test_normal_2_1(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(processing token)
@@ -291,7 +301,7 @@ async def test_normal_2_1(self, processor, db, personal_info_contract):
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
token_2.token_status = 0
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -334,6 +344,16 @@ async def test_normal_2_1(self, processor, db, personal_info_contract):
assert _personal_info.account_address == user_address_1
assert _personal_info.issuer_address == issuer_address
assert _personal_info.personal_info == personal_info_1
+
+ _personal_info_history_list = db.scalars(select(IDXPersonalInfoHistory)).all()
+ assert len(_personal_info_history_list) == 1
+ _personal_info_history = _personal_info_history_list[0]
+ assert _personal_info_history.id == 1
+ assert _personal_info_history.account_address == user_address_1
+ assert _personal_info_history.event_type == PersonalInfoEventType.REGISTER
+ assert _personal_info_history.issuer_address == issuer_address
+ assert _personal_info_history.personal_info == personal_info_1
+
_idx_personal_info_block_number = db.scalars(
select(IDXPersonalInfoBlockNumber).limit(1)
).first()
@@ -380,7 +400,7 @@ async def test_normal_2_2(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(processing token)
@@ -391,7 +411,7 @@ async def test_normal_2_2(self, processor, db, personal_info_contract):
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
token_2.token_status = 0
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -474,6 +494,22 @@ async def test_normal_2_2(self, processor, db, personal_info_contract):
assert _personal_info.account_address == user_address_1
assert _personal_info.issuer_address == issuer_address
assert _personal_info.personal_info == personal_info_2
+
+ _personal_info_history_list = db.scalars(select(IDXPersonalInfoHistory)).all()
+ assert len(_personal_info_history_list) == 2
+ _personal_info_history_1 = _personal_info_history_list[0]
+ assert _personal_info_history_1.id == 1
+ assert _personal_info_history_1.account_address == user_address_1
+ assert _personal_info_history_1.event_type == PersonalInfoEventType.REGISTER
+ assert _personal_info_history_1.issuer_address == issuer_address
+ assert _personal_info_history_1.personal_info == personal_info_1
+ _personal_info_history_2 = _personal_info_history_list[1]
+ assert _personal_info_history_2.id == 2
+ assert _personal_info_history_2.account_address == user_address_1
+ assert _personal_info_history_2.event_type == PersonalInfoEventType.MODIFY
+ assert _personal_info_history_2.issuer_address == issuer_address
+ assert _personal_info_history_2.personal_info == personal_info_2
+
_idx_personal_info_block_number = db.scalars(
select(IDXPersonalInfoBlockNumber).limit(1)
).first()
@@ -520,7 +556,7 @@ async def test_normal_3(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(processing token)
@@ -531,7 +567,7 @@ async def test_normal_3(self, processor, db, personal_info_contract):
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
token_2.token_status = 0
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -614,6 +650,24 @@ async def test_normal_3(self, processor, db, personal_info_contract):
assert _personal_info.account_address == user_address_1
assert _personal_info.issuer_address == issuer_address
assert _personal_info.personal_info == personal_info_2
+
+ _personal_info_history_list = db.scalars(
+ select(IDXPersonalInfoHistory).order_by(IDXPersonalInfoHistory.id)
+ ).all()
+ assert len(_personal_info_history_list) == 2
+ _personal_info_history_1 = _personal_info_history_list[0]
+ assert _personal_info_history_1.id == 1
+ assert _personal_info_history_1.account_address == user_address_1
+ assert _personal_info_history_1.event_type == PersonalInfoEventType.REGISTER
+ assert _personal_info_history_1.issuer_address == issuer_address
+ assert _personal_info_history_1.personal_info == personal_info_1
+ _personal_info_history_2 = _personal_info_history_list[1]
+ assert _personal_info_history_2.id == 2
+ assert _personal_info_history_2.account_address == user_address_1
+ assert _personal_info_history_2.event_type == PersonalInfoEventType.MODIFY
+ assert _personal_info_history_2.issuer_address == issuer_address
+ assert _personal_info_history_2.personal_info == personal_info_2
+
_idx_personal_info_block_number = db.scalars(
select(IDXPersonalInfoBlockNumber).limit(1)
).first()
@@ -662,6 +716,18 @@ async def test_normal_3(self, processor, db, personal_info_contract):
assert _personal_info.account_address == user_address_1
assert _personal_info.issuer_address == issuer_address
assert _personal_info.personal_info == personal_info_3
+
+ _personal_info_history_list = db.scalars(
+ select(IDXPersonalInfoHistory).order_by(IDXPersonalInfoHistory.id)
+ ).all()
+ assert len(_personal_info_history_list) == 3
+ _personal_info_history = _personal_info_history_list[2]
+ assert _personal_info_history.id == 3
+ assert _personal_info_history.account_address == user_address_1
+ assert _personal_info_history.event_type == PersonalInfoEventType.MODIFY
+ assert _personal_info_history.issuer_address == issuer_address
+ assert _personal_info_history.personal_info == personal_info_3
+
_idx_personal_info_block_number = db.scalars(
select(IDXPersonalInfoBlockNumber).limit(1)
).first()
@@ -736,7 +802,7 @@ async def test_normal_4(self, processor, db):
token_1.issuer_address = issuer_address_1
token_1.abi = token_contract1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Issuer2 issues bond token.
@@ -753,7 +819,7 @@ async def test_normal_4(self, processor, db):
token_2.issuer_address = issuer_address_2
token_2.abi = token_contract2.abi
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -845,6 +911,20 @@ async def test_normal_4(self, processor, db):
== personal_info_dict[stored_address_order[i]]
)
+ _personal_info_history_list = db.scalars(select(IDXPersonalInfoHistory)).all()
+ assert len(_personal_info_history_list) == 2
+
+ for i in range(2):
+ _personal_info_history = _personal_info_history_list[i]
+ assert _personal_info_history.id == i + 1
+ assert _personal_info_history.account_address == stored_address_order[i]
+ assert _personal_info_history.event_type == PersonalInfoEventType.REGISTER
+ assert _personal_info_history.issuer_address == stored_address_order[i]
+ assert (
+ _personal_info_history.personal_info
+ == personal_info_dict[stored_address_order[i]]
+ )
+
_idx_personal_info_block_number = db.scalars(
select(IDXPersonalInfoBlockNumber).limit(1)
).first()
@@ -869,130 +949,6 @@ async def test_normal_5(
(LOG.name, logging.DEBUG, "skip process")
)
- #
- # If DB session fails in phase sinking register/modify events, batch logs exception message.
- @pytest.mark.asyncio
- async def test_normal_6(
- self,
- processor: Processor,
- db: Session,
- personal_info_contract,
- caplog: pytest.LogCaptureFixture,
- ):
- user_1 = config_eth_account("user1")
- issuer_address = user_1["address"]
- issuer_private_key = decode_keyfile_json(
- raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
- )
- issuer_rsa_private_key = user_1["rsa_private_key"]
- issuer_rsa_public_key = user_1["rsa_public_key"]
- issuer_rsa_passphrase = "password"
- user_2 = config_eth_account("user2")
- user_address_1 = user_2["address"]
- user_private_key_1 = decode_keyfile_json(
- raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
- )
-
- # Prepare data : Account
- account = Account()
- account.issuer_address = issuer_address
- account.rsa_private_key = issuer_rsa_private_key
- account.rsa_public_key = issuer_rsa_public_key
- account.rsa_passphrase = E2EEUtils.encrypt(issuer_rsa_passphrase)
- account.rsa_status = 3
- db.add(account)
-
- # Prepare data : Token
- token_contract_1 = await deploy_bond_token_contract(
- issuer_address, issuer_private_key, personal_info_contract.address
- )
- token_address_1 = token_contract_1.address
- token_1 = Token()
- token_1.type = TokenType.IBET_STRAIGHT_BOND.value
- token_1.token_address = token_address_1
- token_1.issuer_address = issuer_address
- token_1.abi = token_contract_1.abi
- token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
- db.add(token_1)
-
- # Prepare data : Token(processing token)
- token_2 = Token()
- token_2.type = TokenType.IBET_STRAIGHT_BOND.value
- token_2.token_address = "test1"
- token_2.issuer_address = issuer_address
- token_2.abi = "abi"
- token_2.tx_hash = "tx_hash"
- token_2.token_status = 0
- token_2.version = TokenVersion.V_23_12
- db.add(token_2)
-
- db.commit()
-
- # Register
- personal_info_1 = {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- }
- ciphertext = encrypt_personal_info(
- personal_info_1, issuer_rsa_public_key, issuer_rsa_passphrase
- )
- tx = personal_info_contract.functions.register(
- issuer_address, ciphertext.decode("utf-8")
- ).build_transaction(
- {
- "chainId": CHAIN_ID,
- "from": user_address_1,
- "gas": TX_GAS_LIMIT,
- "gasPrice": 0,
- }
- )
- ContractUtils.send_transaction(tx, user_private_key_1)
-
- # Modify
- personal_info_2 = {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- "birth": "birth_test2",
- "is_corporate": True,
- "tax_category": 20,
- }
- ciphertext = encrypt_personal_info(
- personal_info_2, issuer_rsa_public_key, issuer_rsa_passphrase
- )
- tx = personal_info_contract.functions.modify(
- user_address_1, ciphertext.decode("utf-8")
- ).build_transaction(
- {
- "chainId": CHAIN_ID,
- "from": issuer_address,
- "gas": TX_GAS_LIMIT,
- "gasPrice": 0,
- }
- )
- ContractUtils.send_transaction(tx, issuer_private_key)
-
- with patch.object(Session, "add", side_effect=Exception()):
- # Then execute processor.
- await processor.process()
-
- assert 2 == caplog.record_tuples.count(
- (
- LOG.name,
- logging.ERROR,
- "An exception occurred during event synchronization",
- )
- )
-
###########################################################################
# Error Case
###########################################################################
@@ -1041,7 +997,7 @@ async def test_error_1(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
diff --git a/tests/test_batch_indexer_position_bond.py b/tests/batch/test_indexer_position_bond.py
similarity index 85%
rename from tests/test_batch_indexer_position_bond.py
rename to tests/batch/test_indexer_position_bond.py
index 5d844726..f5103951 100644
--- a/tests/test_batch_indexer_position_bond.py
+++ b/tests/batch/test_indexer_position_bond.py
@@ -18,7 +18,7 @@
"""
import logging
-from datetime import datetime, timedelta
+from datetime import UTC, datetime, timedelta
from unittest.mock import patch
import pytest
@@ -53,9 +53,10 @@
from batch.indexer_position_bond import LOG, Processor, main
from config import CHAIN_ID, TOKEN_CACHE_TTL, TX_GAS_LIMIT, ZERO_ADDRESS
from tests.account_config import config_eth_account
-from tests.utils.contract_utils import (
+from tests.contract_utils import (
IbetExchangeContractTestUtils,
IbetSecurityTokenContractTestUtils as STContractUtils,
+ IbetSecurityTokenDVPContractTestUtils as STDVPContractUtils,
IbetSecurityTokenEscrowContractTestUtils as STEscrowContractUtils,
PersonalInfoContractTestUtils,
)
@@ -144,7 +145,7 @@ async def test_normal_1_1(
token_1.issuer_address = issuer_address
token_1.abi = "abi"
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(processing token)
@@ -155,7 +156,7 @@ async def test_normal_1_1(
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
token_2.token_status = 0
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -205,7 +206,7 @@ async def test_normal_1_2(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(share token)
@@ -215,7 +216,7 @@ async def test_normal_1_2(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -226,7 +227,7 @@ async def test_normal_1_2(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_23_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
# Prepare data : BlockNumber
@@ -294,7 +295,7 @@ async def test_normal_2_1(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(share token)
@@ -304,7 +305,7 @@ async def test_normal_2_1(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -315,7 +316,7 @@ async def test_normal_2_1(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_23_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -402,7 +403,7 @@ async def test_normal_2_2_1(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(share token)
@@ -412,7 +413,7 @@ async def test_normal_2_2_1(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -423,7 +424,7 @@ async def test_normal_2_2_1(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_23_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -515,7 +516,7 @@ async def test_normal_2_2_2(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(share token)
@@ -525,7 +526,7 @@ async def test_normal_2_2_2(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -536,7 +537,7 @@ async def test_normal_2_2_2(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_23_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -619,7 +620,7 @@ async def test_normal_2_2_3(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(share token)
@@ -629,7 +630,7 @@ async def test_normal_2_2_3(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -640,7 +641,7 @@ async def test_normal_2_2_3(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_23_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -770,7 +771,7 @@ async def test_normal_2_3(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(share token)
@@ -780,7 +781,7 @@ async def test_normal_2_3(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -791,7 +792,7 @@ async def test_normal_2_3(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_22_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -913,7 +914,7 @@ async def test_normal_2_4(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(share token)
@@ -923,7 +924,7 @@ async def test_normal_2_4(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -934,7 +935,7 @@ async def test_normal_2_4(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_23_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -1119,7 +1120,7 @@ async def test_normal_2_5(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(share token)
@@ -1129,7 +1130,7 @@ async def test_normal_2_5(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -1140,7 +1141,7 @@ async def test_normal_2_5(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_23_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -1222,7 +1223,7 @@ async def test_normal_2_6(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(share token)
@@ -1232,7 +1233,7 @@ async def test_normal_2_6(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -1243,7 +1244,7 @@ async def test_normal_2_6(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_23_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -1329,7 +1330,7 @@ async def test_normal_2_7(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(share token)
@@ -1339,7 +1340,7 @@ async def test_normal_2_7(self, processor, db, personal_info_contract):
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -1350,7 +1351,7 @@ async def test_normal_2_7(self, processor, db, personal_info_contract):
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_23_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -1469,7 +1470,7 @@ async def test_normal_2_8(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(share token)
@@ -1479,7 +1480,7 @@ async def test_normal_2_8(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -1490,7 +1491,7 @@ async def test_normal_2_8(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_23_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -1619,7 +1620,7 @@ async def test_normal_2_9_1(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(share token)
@@ -1629,7 +1630,7 @@ async def test_normal_2_9_1(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -1640,7 +1641,7 @@ async def test_normal_2_9_1(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_23_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -1766,7 +1767,7 @@ async def test_normal_2_9_2(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -1923,7 +1924,7 @@ async def test_normal_2_9_3(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -2083,7 +2084,7 @@ async def test_normal_2_9_4(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -2243,7 +2244,7 @@ async def test_normal_2_9_5(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -2412,7 +2413,7 @@ async def test_normal_2_9_6(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -2571,7 +2572,7 @@ async def test_normal_2_10_1(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(share token)
@@ -2581,7 +2582,7 @@ async def test_normal_2_10_1(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -2592,7 +2593,7 @@ async def test_normal_2_10_1(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_23_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -2718,7 +2719,7 @@ async def test_normal_2_10_2(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -2876,7 +2877,7 @@ async def test_normal_2_10_3(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -2985,6 +2986,634 @@ async def test_normal_2_10_3(
assert _idx_position_bond_block_number.id == 1
assert _idx_position_bond_block_number.latest_block_number == block_number
+ #
+ # Single Token
+ # Single event logs
+ # - IbetSecurityTokenDVP: DeliveryCreated
+ @pytest.mark.asyncio
+ async def test_normal_2_11_1(
+ self,
+ processor: Processor,
+ db: Session,
+ personal_info_contract,
+ ibet_security_token_dvp_contract,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = user_1["keyfile_json"]
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ # Prepare data : Token
+ token_contract_1 = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ ibet_security_token_dvp_contract.address,
+ )
+ token_address_1 = token_contract_1.address
+ token_1 = Token()
+ token_1.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_1.token_address = token_address_1
+ token_1.issuer_address = issuer_address
+ token_1.abi = token_contract_1.abi
+ token_1.tx_hash = "tx_hash"
+ token_1.version = TokenVersion.V_24_06
+ db.add(token_1)
+
+ # Prepare data : Token(share token)
+ token_2 = Token()
+ token_2.type = TokenType.IBET_SHARE.value
+ token_2.token_address = "test1"
+ token_2.issuer_address = issuer_address
+ token_2.abi = "abi"
+ token_2.tx_hash = "tx_hash"
+ token_2.version = TokenVersion.V_24_06
+ db.add(token_2)
+
+ # Prepare data : Token(processing token)
+ token_3 = Token()
+ token_3.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_3.token_address = "test1"
+ token_3.issuer_address = issuer_address
+ token_3.abi = "abi"
+ token_3.tx_hash = "tx_hash"
+ token_3.token_status = 0
+ token_3.version = TokenVersion.V_24_06
+ db.add(token_3)
+
+ db.commit()
+
+ # Deposit
+ tx = token_contract_1.functions.transferFrom(
+ issuer_address, ibet_security_token_dvp_contract.address, 40
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # Before run(consume accumulated events)
+ await processor.sync_new_logs()
+ _position_list = db.scalars(select(IDXPosition)).all()
+ assert len(_position_list) == 1
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == issuer_address)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == issuer_address
+ assert _position.balance == 100 - 40
+ assert _position.exchange_balance == 40
+ assert _position.exchange_commitment == 0
+ assert _position.pending_transfer == 0
+
+ # EscrowCreated
+ tx = ibet_security_token_dvp_contract.functions.createDelivery(
+ token_contract_1.address, user_address_1, 30, issuer_address, ""
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # Run target process
+ block_number = web3.eth.block_number
+ await processor.sync_new_logs()
+
+ # If we query in one session before and after update some record in another session,
+ # SQLAlchemy will return same result twice. So Expiring all persistent instances within unittest db session.
+ db.expire_all()
+
+ # Assertion
+ _position_list = db.scalars(select(IDXPosition)).all()
+ assert len(_position_list) == 1
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == issuer_address)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == issuer_address
+ assert _position.balance == 100 - 40
+ assert _position.exchange_balance == 40 - 30
+ assert _position.exchange_commitment == 30
+ assert _position.pending_transfer == 0
+ _idx_position_bond_block_number = db.scalars(
+ select(IDXPositionBondBlockNumber).limit(1)
+ ).first()
+ assert _idx_position_bond_block_number.id == 1
+ assert _idx_position_bond_block_number.latest_block_number == block_number
+
+ #
+ # Single Token
+ # Single event logs
+ # - IbetSecurityTokenDVP: DeliveryCanceled
+ @pytest.mark.asyncio
+ async def test_normal_2_11_2(
+ self,
+ processor: Processor,
+ db: Session,
+ personal_info_contract,
+ ibet_security_token_dvp_contract,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_pk_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ user_address_2 = user_3["address"]
+ user_pk_2 = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = user_1["keyfile_json"]
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ # Issuer issues bond token.
+ token_contract = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ transfer_approval_required=False,
+ )
+ token_address_1 = token_contract.address
+ token_1 = Token()
+ token_1.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_1.token_address = token_address_1
+ token_1.issuer_address = issuer_address
+ token_1.abi = token_contract.abi
+ token_1.tx_hash = "tx_hash"
+ token_1.version = TokenVersion.V_24_06
+ db.add(token_1)
+
+ db.commit()
+
+ # Before run(consume accumulated events)
+ await processor.sync_new_logs()
+
+ PersonalInfoContractTestUtils.register(
+ personal_info_contract.address,
+ user_address_1,
+ user_pk_1,
+ [issuer_address, ""],
+ )
+ PersonalInfoContractTestUtils.register(
+ personal_info_contract.address,
+ user_address_2,
+ user_pk_2,
+ [issuer_address, ""],
+ )
+ PersonalInfoContractTestUtils.register(
+ personal_info_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [issuer_address, ""],
+ )
+
+ STContractUtils.transfer(
+ token_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [user_address_1, 30],
+ )
+ STContractUtils.transfer(
+ token_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [user_address_2, 10],
+ )
+
+ # CreateDelivery & CancelDelivery
+ STContractUtils.transfer(
+ token_contract.address,
+ user_address_1,
+ user_pk_1,
+ [ibet_security_token_dvp_contract.address, 30],
+ )
+
+ STDVPContractUtils.create_delivery(
+ ibet_security_token_dvp_contract.address,
+ user_address_1,
+ user_pk_1,
+ [token_contract.address, user_address_2, 10, issuer_address, ""],
+ )
+ latest_delivery_id = STDVPContractUtils.get_latest_delivery_id(
+ ibet_security_token_dvp_contract.address
+ )
+ STDVPContractUtils.cancel_delivery(
+ ibet_security_token_dvp_contract.address,
+ user_address_1,
+ user_pk_1,
+ [latest_delivery_id],
+ )
+
+ # Run target process
+ block_number = web3.eth.block_number
+ await processor.sync_new_logs()
+
+ # Assertion
+ _position_list = db.scalars(select(IDXPosition)).all()
+ assert len(_position_list) == 3
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == issuer_address)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == issuer_address
+ assert _position.balance == 100 - 30 - 10
+ assert _position.exchange_balance == 0
+ assert _position.exchange_commitment == 0
+ assert _position.pending_transfer == 0
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == user_address_1)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == user_address_1
+ assert _position.balance == 0
+ assert _position.exchange_balance == 30
+ assert _position.exchange_commitment == 0
+ assert _position.pending_transfer == 0
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == user_address_2)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == user_address_2
+ assert _position.balance == 10
+ assert _position.exchange_balance == 0
+ assert _position.exchange_commitment == 0
+ assert _position.pending_transfer == 0
+ _idx_position_bond_block_number = db.scalars(
+ select(IDXPositionBondBlockNumber).limit(1)
+ ).first()
+ assert _idx_position_bond_block_number.id == 1
+ assert _idx_position_bond_block_number.latest_block_number == block_number
+
+ #
+ # Single Token
+ # Single event logs
+ # - IbetSecurityTokenDVP: DeliveryFinished
+ @pytest.mark.asyncio
+ async def test_normal_2_11_3(
+ self,
+ processor: Processor,
+ db: Session,
+ personal_info_contract,
+ ibet_security_token_dvp_contract,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_pk_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ user_address_2 = user_3["address"]
+ user_pk_2 = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = user_1["keyfile_json"]
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ # Issuer issues bond token.
+ token_contract = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ transfer_approval_required=False,
+ )
+ token_address_1 = token_contract.address
+ token_1 = Token()
+ token_1.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_1.token_address = token_address_1
+ token_1.issuer_address = issuer_address
+ token_1.abi = token_contract.abi
+ token_1.tx_hash = "tx_hash"
+ token_1.version = TokenVersion.V_24_06
+ db.add(token_1)
+
+ db.commit()
+
+ # Before run(consume accumulated events)
+ await processor.sync_new_logs()
+
+ PersonalInfoContractTestUtils.register(
+ personal_info_contract.address,
+ user_address_1,
+ user_pk_1,
+ [issuer_address, ""],
+ )
+ PersonalInfoContractTestUtils.register(
+ personal_info_contract.address,
+ user_address_2,
+ user_pk_2,
+ [issuer_address, ""],
+ )
+ PersonalInfoContractTestUtils.register(
+ personal_info_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [issuer_address, ""],
+ )
+
+ STContractUtils.transfer(
+ token_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [user_address_1, 30],
+ )
+ STContractUtils.transfer(
+ token_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [user_address_2, 10],
+ )
+
+ # CreateEscrow & CancelEscrow
+ STContractUtils.transfer(
+ token_contract.address,
+ user_address_1,
+ user_pk_1,
+ [ibet_security_token_dvp_contract.address, 30],
+ )
+
+ STDVPContractUtils.create_delivery(
+ ibet_security_token_dvp_contract.address,
+ user_address_1,
+ user_pk_1,
+ [token_contract.address, user_address_2, 10, issuer_address, ""],
+ )
+ latest_delivery_id = STDVPContractUtils.get_latest_delivery_id(
+ ibet_security_token_dvp_contract.address
+ )
+ STDVPContractUtils.confirm_delivery(
+ ibet_security_token_dvp_contract.address,
+ user_address_2,
+ user_pk_2,
+ [latest_delivery_id],
+ )
+ STDVPContractUtils.finish_delivery(
+ ibet_security_token_dvp_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [latest_delivery_id],
+ )
+ # Run target process
+ block_number = web3.eth.block_number
+ await processor.sync_new_logs()
+
+ # Assertion
+ _position_list = db.scalars(select(IDXPosition)).all()
+ assert len(_position_list) == 3
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == issuer_address)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == issuer_address
+ assert _position.balance == 100 - 30 - 10
+ assert _position.exchange_balance == 0
+ assert _position.exchange_commitment == 0
+ assert _position.pending_transfer == 0
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == user_address_1)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == user_address_1
+ assert _position.balance == 0
+ assert _position.exchange_balance == 20
+ assert _position.exchange_commitment == 0
+ assert _position.pending_transfer == 0
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == user_address_2)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == user_address_2
+ assert _position.balance == 10
+ assert _position.exchange_balance == 10
+ assert _position.exchange_commitment == 0
+ assert _position.pending_transfer == 0
+ _idx_position_bond_block_number = db.scalars(
+ select(IDXPositionBondBlockNumber).limit(1)
+ ).first()
+ assert _idx_position_bond_block_number.id == 1
+ assert _idx_position_bond_block_number.latest_block_number == block_number
+
+ #
+ # Single Token
+ # Single event logs
+ # - IbetSecurityTokenDVP: DeliveryAborted
+ @pytest.mark.asyncio
+ async def test_normal_2_11_4(
+ self,
+ processor: Processor,
+ db: Session,
+ personal_info_contract,
+ ibet_security_token_dvp_contract,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_pk_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ user_address_2 = user_3["address"]
+ user_pk_2 = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = user_1["keyfile_json"]
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ # Issuer issues bond token.
+ token_contract = await deploy_bond_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ transfer_approval_required=False,
+ )
+ token_address_1 = token_contract.address
+ token_1 = Token()
+ token_1.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_1.token_address = token_address_1
+ token_1.issuer_address = issuer_address
+ token_1.abi = token_contract.abi
+ token_1.tx_hash = "tx_hash"
+ token_1.version = TokenVersion.V_24_06
+ db.add(token_1)
+
+ db.commit()
+
+ # Before run(consume accumulated events)
+ await processor.sync_new_logs()
+
+ PersonalInfoContractTestUtils.register(
+ personal_info_contract.address,
+ user_address_1,
+ user_pk_1,
+ [issuer_address, ""],
+ )
+ PersonalInfoContractTestUtils.register(
+ personal_info_contract.address,
+ user_address_2,
+ user_pk_2,
+ [issuer_address, ""],
+ )
+ PersonalInfoContractTestUtils.register(
+ personal_info_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [issuer_address, ""],
+ )
+
+ STContractUtils.transfer(
+ token_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [user_address_1, 30],
+ )
+ STContractUtils.transfer(
+ token_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [user_address_2, 10],
+ )
+
+ # CreateDelivery & CancelDelivery
+ STContractUtils.transfer(
+ token_contract.address,
+ user_address_1,
+ user_pk_1,
+ [ibet_security_token_dvp_contract.address, 30],
+ )
+
+ STDVPContractUtils.create_delivery(
+ ibet_security_token_dvp_contract.address,
+ user_address_1,
+ user_pk_1,
+ [token_contract.address, user_address_2, 10, issuer_address, ""],
+ )
+ latest_delivery_id = STDVPContractUtils.get_latest_delivery_id(
+ ibet_security_token_dvp_contract.address
+ )
+ STDVPContractUtils.confirm_delivery(
+ ibet_security_token_dvp_contract.address,
+ user_address_2,
+ user_pk_2,
+ [latest_delivery_id],
+ )
+ STDVPContractUtils.abort_delivery(
+ ibet_security_token_dvp_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [latest_delivery_id],
+ )
+
+ # Run target process
+ block_number = web3.eth.block_number
+ await processor.sync_new_logs()
+
+ # Assertion
+ _position_list = db.scalars(select(IDXPosition)).all()
+ assert len(_position_list) == 3
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == issuer_address)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == issuer_address
+ assert _position.balance == 100 - 30 - 10
+ assert _position.exchange_balance == 0
+ assert _position.exchange_commitment == 0
+ assert _position.pending_transfer == 0
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == user_address_1)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == user_address_1
+ assert _position.balance == 0
+ assert _position.exchange_balance == 30
+ assert _position.exchange_commitment == 0
+ assert _position.pending_transfer == 0
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == user_address_2)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == user_address_2
+ assert _position.balance == 10
+ assert _position.exchange_balance == 0
+ assert _position.exchange_commitment == 0
+ assert _position.pending_transfer == 0
+ _idx_position_bond_block_number = db.scalars(
+ select(IDXPositionBondBlockNumber).limit(1)
+ ).first()
+ assert _idx_position_bond_block_number.id == 1
+ assert _idx_position_bond_block_number.latest_block_number == block_number
+
#
# Single Token
# Multi event logs
@@ -3027,7 +3656,7 @@ async def test_normal_3_1(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(share token)
@@ -3037,7 +3666,7 @@ async def test_normal_3_1(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -3048,7 +3677,7 @@ async def test_normal_3_1(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_23_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -3190,7 +3819,7 @@ async def test_normal_3_2(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(share token)
@@ -3200,7 +3829,7 @@ async def test_normal_3_2(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -3394,7 +4023,7 @@ async def test_normal_3_3(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -3566,7 +4195,7 @@ async def test_normal_3_4(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -3722,7 +4351,7 @@ async def test_normal_4(
token_1.issuer_address = issuer_address
token_1.abi = token_contract1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Issuer issues bond token.
@@ -3740,7 +4369,7 @@ async def test_normal_4(
token_2.issuer_address = issuer_address
token_2.abi = token_contract2.abi
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -3960,7 +4589,7 @@ async def test_normal_6_1(
token_1.issuer_address = issuer_address
token_1.abi = token_contract1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -4001,7 +4630,7 @@ async def test_normal_6_1(
token_2.issuer_address = issuer_address
token_2.abi = token_contract2.abi
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -4056,7 +4685,7 @@ async def test_normal_6_2(
token_1.issuer_address = issuer_address
token_1.abi = token_contract1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
token_1.initial_position_synced = True # already synced
db.add(token_1)
@@ -4110,7 +4739,7 @@ async def test_error_1(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
token_attr = {
@@ -4158,10 +4787,10 @@ async def test_error_1(
token_cache = TokenCache()
token_cache.token_address = token_address_1
token_cache.attributes = token_attr
- token_cache.cached_datetime = datetime.utcnow()
- token_cache.expiration_datetime = datetime.utcnow() + timedelta(
- seconds=TOKEN_CACHE_TTL
- )
+ token_cache.cached_datetime = datetime.now(UTC).replace(tzinfo=None)
+ token_cache.expiration_datetime = datetime.now(UTC).replace(
+ tzinfo=None
+ ) + timedelta(seconds=TOKEN_CACHE_TTL)
db.add(token_cache)
db.commit()
diff --git a/tests/test_batch_indexer_position_share.py b/tests/batch/test_indexer_position_share.py
similarity index 85%
rename from tests/test_batch_indexer_position_share.py
rename to tests/batch/test_indexer_position_share.py
index 4a0c8375..2bc2627d 100644
--- a/tests/test_batch_indexer_position_share.py
+++ b/tests/batch/test_indexer_position_share.py
@@ -18,7 +18,7 @@
"""
import logging
-from datetime import datetime, timedelta
+from datetime import UTC, datetime, timedelta
from unittest import mock
from unittest.mock import patch
@@ -48,15 +48,16 @@
TokenType,
TokenVersion,
)
-from app.utils.contract_utils import AsyncContractUtils, ContractUtils
+from app.utils.contract_utils import ContractUtils
from app.utils.e2ee_utils import E2EEUtils
from app.utils.web3_utils import AsyncWeb3Wrapper, Web3Wrapper
from batch.indexer_position_share import LOG, Processor, main
from config import CHAIN_ID, TOKEN_CACHE_TTL, TX_GAS_LIMIT, ZERO_ADDRESS
from tests.account_config import config_eth_account
-from tests.utils.contract_utils import (
+from tests.contract_utils import (
IbetExchangeContractTestUtils,
IbetSecurityTokenContractTestUtils as STContractUtils,
+ IbetSecurityTokenDVPContractTestUtils as STDVPContractUtils,
IbetSecurityTokenEscrowContractTestUtils as STEscrowContractUtils,
PersonalInfoContractTestUtils,
)
@@ -150,7 +151,7 @@ async def test_normal_1_1(
token_1.issuer_address = issuer_address
token_1.abi = "abi"
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(processing token)
@@ -161,7 +162,7 @@ async def test_normal_1_1(
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
token_2.token_status = 0
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -211,7 +212,7 @@ async def test_normal_1_2(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(bond token)
@@ -221,7 +222,7 @@ async def test_normal_1_2(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -232,7 +233,7 @@ async def test_normal_1_2(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_22_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
# Prepare data : BlockNumber
@@ -300,7 +301,7 @@ async def test_normal_2_1(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(bond token)
@@ -310,7 +311,7 @@ async def test_normal_2_1(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -321,7 +322,7 @@ async def test_normal_2_1(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_22_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -408,7 +409,7 @@ async def test_normal_2_2_1(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(bond token)
@@ -418,7 +419,7 @@ async def test_normal_2_2_1(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -429,7 +430,7 @@ async def test_normal_2_2_1(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_22_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -521,7 +522,7 @@ async def test_normal_2_2_2(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(bond token)
@@ -531,7 +532,7 @@ async def test_normal_2_2_2(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -542,7 +543,7 @@ async def test_normal_2_2_2(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_22_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -625,7 +626,7 @@ async def test_normal_2_2_3(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(bond token)
@@ -635,7 +636,7 @@ async def test_normal_2_2_3(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -646,7 +647,7 @@ async def test_normal_2_2_3(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_22_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -776,7 +777,7 @@ async def test_normal_2_3(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(bond token)
@@ -786,7 +787,7 @@ async def test_normal_2_3(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -797,7 +798,7 @@ async def test_normal_2_3(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_22_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -919,7 +920,7 @@ async def test_normal_2_4(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(bond token)
@@ -929,7 +930,7 @@ async def test_normal_2_4(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -940,7 +941,7 @@ async def test_normal_2_4(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_22_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -1125,7 +1126,7 @@ async def test_normal_2_5(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(bond token)
@@ -1135,7 +1136,7 @@ async def test_normal_2_5(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -1146,7 +1147,7 @@ async def test_normal_2_5(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_22_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -1228,7 +1229,7 @@ async def test_normal_2_6(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(bond token)
@@ -1238,7 +1239,7 @@ async def test_normal_2_6(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -1249,7 +1250,7 @@ async def test_normal_2_6(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_22_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -1337,7 +1338,7 @@ async def test_normal_2_7(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(bond token)
@@ -1347,7 +1348,7 @@ async def test_normal_2_7(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -1358,7 +1359,7 @@ async def test_normal_2_7(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_22_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -1477,7 +1478,7 @@ async def test_normal_2_8(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(bond token)
@@ -1487,7 +1488,7 @@ async def test_normal_2_8(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -1498,7 +1499,7 @@ async def test_normal_2_8(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_22_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -1627,7 +1628,7 @@ async def test_normal_2_9_1(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(bond token)
@@ -1637,7 +1638,7 @@ async def test_normal_2_9_1(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -1648,7 +1649,7 @@ async def test_normal_2_9_1(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_22_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -1774,7 +1775,7 @@ async def test_normal_2_9_2(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -1931,7 +1932,7 @@ async def test_normal_2_9_3(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -2091,7 +2092,7 @@ async def test_normal_2_9_4(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -2251,7 +2252,7 @@ async def test_normal_2_9_5(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -2420,7 +2421,7 @@ async def test_normal_2_9_6(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -2579,7 +2580,7 @@ async def test_normal_2_10_1(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(bond token)
@@ -2589,7 +2590,7 @@ async def test_normal_2_10_1(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -2600,7 +2601,7 @@ async def test_normal_2_10_1(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_22_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -2726,7 +2727,7 @@ async def test_normal_2_10_2(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -2884,7 +2885,7 @@ async def test_normal_2_10_3(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -2993,6 +2994,634 @@ async def test_normal_2_10_3(
assert _idx_position_share_block_number.id == 1
assert _idx_position_share_block_number.latest_block_number == block_number
+ #
+ # Single Token
+ # Single event logs
+ # - IbetSecurityTokenDVP: DeliveryCreated
+ @pytest.mark.asyncio
+ async def test_normal_2_11_1(
+ self,
+ processor: Processor,
+ db: Session,
+ personal_info_contract,
+ ibet_security_token_dvp_contract,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = user_1["keyfile_json"]
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ # Prepare data : Token
+ token_contract_1 = await deploy_share_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ ibet_security_token_dvp_contract.address,
+ )
+ token_address_1 = token_contract_1.address
+ token_1 = Token()
+ token_1.type = TokenType.IBET_SHARE.value
+ token_1.token_address = token_address_1
+ token_1.issuer_address = issuer_address
+ token_1.abi = token_contract_1.abi
+ token_1.tx_hash = "tx_hash"
+ token_1.version = TokenVersion.V_24_06
+ db.add(token_1)
+
+ # Prepare data : Token(bond token)
+ token_2 = Token()
+ token_2.type = TokenType.IBET_STRAIGHT_BOND.value
+ token_2.token_address = "test1"
+ token_2.issuer_address = issuer_address
+ token_2.abi = "abi"
+ token_2.tx_hash = "tx_hash"
+ token_2.version = TokenVersion.V_24_06
+ db.add(token_2)
+
+ # Prepare data : Token(processing token)
+ token_3 = Token()
+ token_3.type = TokenType.IBET_SHARE.value
+ token_3.token_address = "test1"
+ token_3.issuer_address = issuer_address
+ token_3.abi = "abi"
+ token_3.tx_hash = "tx_hash"
+ token_3.token_status = 0
+ token_3.version = TokenVersion.V_24_06
+ db.add(token_3)
+
+ db.commit()
+
+ # Deposit
+ tx = token_contract_1.functions.transferFrom(
+ issuer_address, ibet_security_token_dvp_contract.address, 40
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # Before run(consume accumulated events)
+ await processor.sync_new_logs()
+ _position_list = db.scalars(select(IDXPosition)).all()
+ assert len(_position_list) == 1
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == issuer_address)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == issuer_address
+ assert _position.balance == 100 - 40
+ assert _position.exchange_balance == 40
+ assert _position.exchange_commitment == 0
+ assert _position.pending_transfer == 0
+
+ # EscrowCreated
+ tx = ibet_security_token_dvp_contract.functions.createDelivery(
+ token_contract_1.address, user_address_1, 30, issuer_address, ""
+ ).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": issuer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, issuer_private_key)
+
+ # Run target process
+ block_number = web3.eth.block_number
+ await processor.sync_new_logs()
+
+ # If we query in one session before and after update some record in another session,
+ # SQLAlchemy will return same result twice. So Expiring all persistent instances within unittest db session.
+ db.expire_all()
+
+ # Assertion
+ _position_list = db.scalars(select(IDXPosition)).all()
+ assert len(_position_list) == 1
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == issuer_address)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == issuer_address
+ assert _position.balance == 100 - 40
+ assert _position.exchange_balance == 40 - 30
+ assert _position.exchange_commitment == 30
+ assert _position.pending_transfer == 0
+ _idx_position_share_block_number = db.scalars(
+ select(IDXPositionShareBlockNumber).limit(1)
+ ).first()
+ assert _idx_position_share_block_number.id == 1
+ assert _idx_position_share_block_number.latest_block_number == block_number
+
+ #
+ # Single Token
+ # Single event logs
+ # - IbetSecurityTokenDVP: DeliveryCanceled
+ @pytest.mark.asyncio
+ async def test_normal_2_11_2(
+ self,
+ processor: Processor,
+ db: Session,
+ personal_info_contract,
+ ibet_security_token_dvp_contract,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_pk_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ user_address_2 = user_3["address"]
+ user_pk_2 = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = user_1["keyfile_json"]
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ # Issuer issues share token.
+ token_contract = await deploy_share_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ transfer_approval_required=False,
+ )
+ token_address_1 = token_contract.address
+ token_1 = Token()
+ token_1.type = TokenType.IBET_SHARE.value
+ token_1.token_address = token_address_1
+ token_1.issuer_address = issuer_address
+ token_1.abi = token_contract.abi
+ token_1.tx_hash = "tx_hash"
+ token_1.version = TokenVersion.V_24_06
+ db.add(token_1)
+
+ db.commit()
+
+ # Before run(consume accumulated events)
+ await processor.sync_new_logs()
+
+ PersonalInfoContractTestUtils.register(
+ personal_info_contract.address,
+ user_address_1,
+ user_pk_1,
+ [issuer_address, ""],
+ )
+ PersonalInfoContractTestUtils.register(
+ personal_info_contract.address,
+ user_address_2,
+ user_pk_2,
+ [issuer_address, ""],
+ )
+ PersonalInfoContractTestUtils.register(
+ personal_info_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [issuer_address, ""],
+ )
+
+ STContractUtils.transfer(
+ token_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [user_address_1, 30],
+ )
+ STContractUtils.transfer(
+ token_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [user_address_2, 10],
+ )
+
+ # CreateDelivery & CancelDelivery
+ STContractUtils.transfer(
+ token_contract.address,
+ user_address_1,
+ user_pk_1,
+ [ibet_security_token_dvp_contract.address, 30],
+ )
+
+ STDVPContractUtils.create_delivery(
+ ibet_security_token_dvp_contract.address,
+ user_address_1,
+ user_pk_1,
+ [token_contract.address, user_address_2, 10, issuer_address, ""],
+ )
+ latest_delivery_id = STDVPContractUtils.get_latest_delivery_id(
+ ibet_security_token_dvp_contract.address
+ )
+ STDVPContractUtils.cancel_delivery(
+ ibet_security_token_dvp_contract.address,
+ user_address_1,
+ user_pk_1,
+ [latest_delivery_id],
+ )
+
+ # Run target process
+ block_number = web3.eth.block_number
+ await processor.sync_new_logs()
+
+ # Assertion
+ _position_list = db.scalars(select(IDXPosition)).all()
+ assert len(_position_list) == 3
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == issuer_address)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == issuer_address
+ assert _position.balance == 100 - 30 - 10
+ assert _position.exchange_balance == 0
+ assert _position.exchange_commitment == 0
+ assert _position.pending_transfer == 0
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == user_address_1)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == user_address_1
+ assert _position.balance == 0
+ assert _position.exchange_balance == 30
+ assert _position.exchange_commitment == 0
+ assert _position.pending_transfer == 0
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == user_address_2)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == user_address_2
+ assert _position.balance == 10
+ assert _position.exchange_balance == 0
+ assert _position.exchange_commitment == 0
+ assert _position.pending_transfer == 0
+ _idx_position_share_block_number = db.scalars(
+ select(IDXPositionShareBlockNumber).limit(1)
+ ).first()
+ assert _idx_position_share_block_number.id == 1
+ assert _idx_position_share_block_number.latest_block_number == block_number
+
+ #
+ # Single Token
+ # Single event logs
+ # - IbetSecurityTokenDVP: DeliveryFinished
+ @pytest.mark.asyncio
+ async def test_normal_2_11_3(
+ self,
+ processor: Processor,
+ db: Session,
+ personal_info_contract,
+ ibet_security_token_dvp_contract,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_pk_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ user_address_2 = user_3["address"]
+ user_pk_2 = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = user_1["keyfile_json"]
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ # Issuer issues share token.
+ token_contract = await deploy_share_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ transfer_approval_required=False,
+ )
+ token_address_1 = token_contract.address
+ token_1 = Token()
+ token_1.type = TokenType.IBET_SHARE.value
+ token_1.token_address = token_address_1
+ token_1.issuer_address = issuer_address
+ token_1.abi = token_contract.abi
+ token_1.tx_hash = "tx_hash"
+ token_1.version = TokenVersion.V_24_06
+ db.add(token_1)
+
+ db.commit()
+
+ # Before run(consume accumulated events)
+ await processor.sync_new_logs()
+
+ PersonalInfoContractTestUtils.register(
+ personal_info_contract.address,
+ user_address_1,
+ user_pk_1,
+ [issuer_address, ""],
+ )
+ PersonalInfoContractTestUtils.register(
+ personal_info_contract.address,
+ user_address_2,
+ user_pk_2,
+ [issuer_address, ""],
+ )
+ PersonalInfoContractTestUtils.register(
+ personal_info_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [issuer_address, ""],
+ )
+
+ STContractUtils.transfer(
+ token_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [user_address_1, 30],
+ )
+ STContractUtils.transfer(
+ token_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [user_address_2, 10],
+ )
+
+ # CreateEscrow & CancelEscrow
+ STContractUtils.transfer(
+ token_contract.address,
+ user_address_1,
+ user_pk_1,
+ [ibet_security_token_dvp_contract.address, 30],
+ )
+
+ STDVPContractUtils.create_delivery(
+ ibet_security_token_dvp_contract.address,
+ user_address_1,
+ user_pk_1,
+ [token_contract.address, user_address_2, 10, issuer_address, ""],
+ )
+ latest_delivery_id = STDVPContractUtils.get_latest_delivery_id(
+ ibet_security_token_dvp_contract.address
+ )
+ STDVPContractUtils.confirm_delivery(
+ ibet_security_token_dvp_contract.address,
+ user_address_2,
+ user_pk_2,
+ [latest_delivery_id],
+ )
+ STDVPContractUtils.finish_delivery(
+ ibet_security_token_dvp_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [latest_delivery_id],
+ )
+ # Run target process
+ block_number = web3.eth.block_number
+ await processor.sync_new_logs()
+
+ # Assertion
+ _position_list = db.scalars(select(IDXPosition)).all()
+ assert len(_position_list) == 3
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == issuer_address)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == issuer_address
+ assert _position.balance == 100 - 30 - 10
+ assert _position.exchange_balance == 0
+ assert _position.exchange_commitment == 0
+ assert _position.pending_transfer == 0
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == user_address_1)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == user_address_1
+ assert _position.balance == 0
+ assert _position.exchange_balance == 20
+ assert _position.exchange_commitment == 0
+ assert _position.pending_transfer == 0
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == user_address_2)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == user_address_2
+ assert _position.balance == 10
+ assert _position.exchange_balance == 10
+ assert _position.exchange_commitment == 0
+ assert _position.pending_transfer == 0
+ _idx_position_share_block_number = db.scalars(
+ select(IDXPositionShareBlockNumber).limit(1)
+ ).first()
+ assert _idx_position_share_block_number.id == 1
+ assert _idx_position_share_block_number.latest_block_number == block_number
+
+ #
+ # Single Token
+ # Single event logs
+ # - IbetSecurityTokenDVP: DeliveryAborted
+ @pytest.mark.asyncio
+ async def test_normal_2_11_4(
+ self,
+ processor: Processor,
+ db: Session,
+ personal_info_contract,
+ ibet_security_token_dvp_contract,
+ ):
+ user_1 = config_eth_account("user1")
+ issuer_address = user_1["address"]
+ issuer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_2 = config_eth_account("user2")
+ user_address_1 = user_2["address"]
+ user_pk_1 = decode_keyfile_json(
+ raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
+ )
+ user_3 = config_eth_account("user3")
+ user_address_2 = user_3["address"]
+ user_pk_2 = decode_keyfile_json(
+ raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Prepare data : Account
+ account = Account()
+ account.issuer_address = issuer_address
+ account.keyfile = user_1["keyfile_json"]
+ account.eoa_password = E2EEUtils.encrypt("password")
+ db.add(account)
+
+ # Issuer issues share token.
+ token_contract = await deploy_share_token_contract(
+ issuer_address,
+ issuer_private_key,
+ personal_info_contract.address,
+ tradable_exchange_contract_address=ibet_security_token_dvp_contract.address,
+ transfer_approval_required=False,
+ )
+ token_address_1 = token_contract.address
+ token_1 = Token()
+ token_1.type = TokenType.IBET_SHARE.value
+ token_1.token_address = token_address_1
+ token_1.issuer_address = issuer_address
+ token_1.abi = token_contract.abi
+ token_1.tx_hash = "tx_hash"
+ token_1.version = TokenVersion.V_24_06
+ db.add(token_1)
+
+ db.commit()
+
+ # Before run(consume accumulated events)
+ await processor.sync_new_logs()
+
+ PersonalInfoContractTestUtils.register(
+ personal_info_contract.address,
+ user_address_1,
+ user_pk_1,
+ [issuer_address, ""],
+ )
+ PersonalInfoContractTestUtils.register(
+ personal_info_contract.address,
+ user_address_2,
+ user_pk_2,
+ [issuer_address, ""],
+ )
+ PersonalInfoContractTestUtils.register(
+ personal_info_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [issuer_address, ""],
+ )
+
+ STContractUtils.transfer(
+ token_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [user_address_1, 30],
+ )
+ STContractUtils.transfer(
+ token_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [user_address_2, 10],
+ )
+
+ # CreateDelivery & CancelDelivery
+ STContractUtils.transfer(
+ token_contract.address,
+ user_address_1,
+ user_pk_1,
+ [ibet_security_token_dvp_contract.address, 30],
+ )
+
+ STDVPContractUtils.create_delivery(
+ ibet_security_token_dvp_contract.address,
+ user_address_1,
+ user_pk_1,
+ [token_contract.address, user_address_2, 10, issuer_address, ""],
+ )
+ latest_delivery_id = STDVPContractUtils.get_latest_delivery_id(
+ ibet_security_token_dvp_contract.address
+ )
+ STDVPContractUtils.confirm_delivery(
+ ibet_security_token_dvp_contract.address,
+ user_address_2,
+ user_pk_2,
+ [latest_delivery_id],
+ )
+ STDVPContractUtils.abort_delivery(
+ ibet_security_token_dvp_contract.address,
+ issuer_address,
+ issuer_private_key,
+ [latest_delivery_id],
+ )
+
+ # Run target process
+ block_number = web3.eth.block_number
+ await processor.sync_new_logs()
+
+ # Assertion
+ _position_list = db.scalars(select(IDXPosition)).all()
+ assert len(_position_list) == 3
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == issuer_address)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == issuer_address
+ assert _position.balance == 100 - 30 - 10
+ assert _position.exchange_balance == 0
+ assert _position.exchange_commitment == 0
+ assert _position.pending_transfer == 0
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == user_address_1)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == user_address_1
+ assert _position.balance == 0
+ assert _position.exchange_balance == 30
+ assert _position.exchange_commitment == 0
+ assert _position.pending_transfer == 0
+ _position = db.scalars(
+ select(IDXPosition)
+ .where(IDXPosition.account_address == user_address_2)
+ .limit(1)
+ ).first()
+ assert _position.token_address == token_address_1
+ assert _position.account_address == user_address_2
+ assert _position.balance == 10
+ assert _position.exchange_balance == 0
+ assert _position.exchange_commitment == 0
+ assert _position.pending_transfer == 0
+ _idx_position_share_block_number = db.scalars(
+ select(IDXPositionShareBlockNumber).limit(1)
+ ).first()
+ assert _idx_position_share_block_number.id == 1
+ assert _idx_position_share_block_number.latest_block_number == block_number
+
#
# Single Token
# Multi event logs
@@ -3035,7 +3664,7 @@ async def test_normal_3_1(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(bond token)
@@ -3045,7 +3674,7 @@ async def test_normal_3_1(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -3056,7 +3685,7 @@ async def test_normal_3_1(
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_22_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
@@ -3198,7 +3827,7 @@ async def test_normal_3_2(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(share token)
@@ -3208,7 +3837,7 @@ async def test_normal_3_2(
token_2.issuer_address = issuer_address
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -3402,7 +4031,7 @@ async def test_normal_3_3(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -3574,7 +4203,7 @@ async def test_normal_3_4(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -3730,7 +4359,7 @@ async def test_normal_4(
token_1.issuer_address = issuer_address
token_1.abi = token_contract1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Issuer issues share token.
@@ -3748,7 +4377,7 @@ async def test_normal_4(
token_2.issuer_address = issuer_address
token_2.abi = token_contract2.abi
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -3969,7 +4598,7 @@ async def test_normal_6_1(
token_1.issuer_address = issuer_address
token_1.abi = token_contract1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -4010,7 +4639,7 @@ async def test_normal_6_1(
token_2.issuer_address = issuer_address
token_2.abi = token_contract2.abi
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -4065,7 +4694,7 @@ async def test_normal_6_2(
token_1.issuer_address = issuer_address
token_1.abi = token_contract1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
token_1.initial_position_synced = True # already synced
db.add(token_1)
@@ -4121,7 +4750,7 @@ async def test_error_1(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : TokenCache
@@ -4151,10 +4780,10 @@ async def test_error_1(
token_cache = TokenCache()
token_cache.token_address = token_address_1
token_cache.attributes = token_attr
- token_cache.cached_datetime = datetime.utcnow()
- token_cache.expiration_datetime = datetime.utcnow() + timedelta(
- seconds=TOKEN_CACHE_TTL
- )
+ token_cache.cached_datetime = datetime.now(UTC).replace(tzinfo=None)
+ token_cache.expiration_datetime = datetime.now(UTC).replace(
+ tzinfo=None
+ ) + timedelta(seconds=TOKEN_CACHE_TTL)
db.add(token_cache)
db.commit()
diff --git a/tests/test_batch_indexer_token_cache.py b/tests/batch/test_indexer_token_cache.py
similarity index 96%
rename from tests/test_batch_indexer_token_cache.py
rename to tests/batch/test_indexer_token_cache.py
index a612b88e..5c37f17a 100644
--- a/tests/test_batch_indexer_token_cache.py
+++ b/tests/batch/test_indexer_token_cache.py
@@ -18,10 +18,9 @@
"""
import logging
-import time
-from datetime import datetime
+from datetime import UTC, datetime
from unittest import mock
-from unittest.mock import AsyncMock, MagicMock, patch
+from unittest.mock import AsyncMock, patch
import pytest
from eth_keyfile import decode_keyfile_json
@@ -162,7 +161,7 @@ async def test_normal_1_1(self, processor, db, personal_info_contract):
token_1.abi = "abi"
token_1.tx_hash = "tx_hash"
token_1.token_status = 0
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -208,7 +207,7 @@ async def test_normal_1_2(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token
@@ -222,7 +221,7 @@ async def test_normal_1_2(self, processor, db, personal_info_contract):
token_2.issuer_address = issuer_address
token_2.abi = token_contract_2.abi
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : Token(processing token)
@@ -233,12 +232,12 @@ async def test_normal_1_2(self, processor, db, personal_info_contract):
token_3.abi = "abi"
token_3.tx_hash = "tx_hash"
token_3.token_status = 0
- token_3.version = TokenVersion.V_23_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
db.commit()
- before_cache_time = datetime.utcnow()
+ before_cache_time = datetime.now(UTC).replace(tzinfo=None)
sleep_mock = AsyncMock()
sleep_mock.return_value = 0
@@ -268,6 +267,7 @@ async def test_normal_1_2(self, processor, db, personal_info_contract):
"privacy_policy": "",
"status": True,
"personal_info_contract_address": personal_info_contract.address,
+ "require_personal_info_registered": True,
"transferable": True,
"is_offering": False,
"transfer_approval_required": False,
@@ -304,6 +304,7 @@ async def test_normal_1_2(self, processor, db, personal_info_contract):
"memo": "",
"name": "token.name",
"personal_info_contract_address": personal_info_contract.address,
+ "require_personal_info_registered": True,
"principal_value": 30,
"privacy_policy": "",
"status": True,
@@ -353,7 +354,7 @@ async def test_error_1(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
diff --git a/tests/test_batch_indexer_token_holders.py b/tests/batch/test_indexer_token_holders.py
similarity index 99%
rename from tests/test_batch_indexer_token_holders.py
rename to tests/batch/test_indexer_token_holders.py
index 1826f415..9a27c225 100644
--- a/tests/test_batch_indexer_token_holders.py
+++ b/tests/batch/test_indexer_token_holders.py
@@ -49,7 +49,7 @@
from batch.indexer_token_holders import LOG, Processor, main
from config import ZERO_ADDRESS
from tests.account_config import config_eth_account
-from tests.utils.contract_utils import (
+from tests.contract_utils import (
IbetExchangeContractTestUtils,
IbetSecurityTokenContractTestUtils as STContractUtils,
IbetSecurityTokenEscrowContractTestUtils as STEscrowContractUtils,
@@ -249,7 +249,7 @@ async def test_normal_1(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
PersonalInfoContractTestUtils.register(
@@ -624,7 +624,7 @@ async def test_normal_2(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
PersonalInfoContractTestUtils.register(
@@ -846,7 +846,7 @@ async def test_normal_3(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
PersonalInfoContractTestUtils.register(
@@ -1037,7 +1037,7 @@ async def test_normal_4(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
PersonalInfoContractTestUtils.register(
@@ -1426,7 +1426,7 @@ async def test_normal_5(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
PersonalInfoContractTestUtils.register(
@@ -1648,7 +1648,7 @@ async def test_normal_6(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
PersonalInfoContractTestUtils.register(
@@ -1843,7 +1843,7 @@ async def test_normal_7(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
PersonalInfoContractTestUtils.register(
@@ -1960,7 +1960,7 @@ async def test_normal_8(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
PersonalInfoContractTestUtils.register(
@@ -2145,7 +2145,7 @@ async def test_normal_9(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
PersonalInfoContractTestUtils.register(
@@ -2298,7 +2298,7 @@ async def test_normal_10(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Insert collection record with above token and checkpoint block number
@@ -2475,7 +2475,7 @@ async def test_error_3(
token_1.issuer_address = issuer_address
token_1.abi = token_contract.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
PersonalInfoContractTestUtils.register(
diff --git a/tests/test_batch_indexer_transfer.py b/tests/batch/test_indexer_transfer.py
similarity index 94%
rename from tests/test_batch_indexer_transfer.py
rename to tests/batch/test_indexer_transfer.py
index 5b642f93..fc83f781 100644
--- a/tests/test_batch_indexer_transfer.py
+++ b/tests/batch/test_indexer_transfer.py
@@ -19,7 +19,7 @@
import json
import logging
-from datetime import datetime
+from datetime import UTC, datetime
from unittest import mock
from unittest.mock import patch
@@ -53,7 +53,7 @@
from batch.indexer_transfer import LOG, Processor, main
from config import CHAIN_ID, TX_GAS_LIMIT
from tests.account_config import config_eth_account
-from tests.utils.contract_utils import PersonalInfoContractTestUtils
+from tests.contract_utils import PersonalInfoContractTestUtils
web3 = Web3Wrapper()
async_web3 = AsyncWeb3Wrapper()
@@ -173,7 +173,7 @@ async def test_normal_1_1(self, processor, db, personal_info_contract):
token_1.abi = "abi"
token_1.tx_hash = "tx_hash"
token_1.token_status = 0
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -214,7 +214,7 @@ async def test_normal_1_2(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(processing token)
@@ -225,7 +225,7 @@ async def test_normal_1_2(self, processor, db, personal_info_contract):
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
token_2.token_status = 0
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : BlockNumber
@@ -288,7 +288,7 @@ async def test_normal_2_1(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(processing token)
@@ -299,7 +299,7 @@ async def test_normal_2_1(self, processor, db, personal_info_contract):
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
token_2.token_status = 0
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -364,9 +364,9 @@ async def test_normal_2_1(self, processor, db, personal_info_contract):
assert _transfer.source_event == IDXTransferSourceEventType.TRANSFER.value
assert _transfer.data is None
block = web3.eth.get_block(tx_receipt_1["blockNumber"])
- assert _transfer.block_timestamp == datetime.utcfromtimestamp(
- block["timestamp"]
- )
+ assert _transfer.block_timestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
_transfer = _transfer_list[1]
assert _transfer.id == 2
@@ -378,9 +378,9 @@ async def test_normal_2_1(self, processor, db, personal_info_contract):
assert _transfer.source_event == IDXTransferSourceEventType.UNLOCK.value
assert _transfer.data == {"message": "unlock"}
block = web3.eth.get_block(tx_receipt_2["blockNumber"])
- assert _transfer.block_timestamp == datetime.utcfromtimestamp(
- block["timestamp"]
- )
+ assert _transfer.block_timestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
_idx_transfer_block_number = db.scalars(
select(IDXTransferBlockNumber).limit(1)
@@ -424,7 +424,7 @@ async def test_normal_2_2(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(processing token)
@@ -435,7 +435,7 @@ async def test_normal_2_2(self, processor, db, personal_info_contract):
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
token_2.token_status = 0
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -522,7 +522,7 @@ async def test_normal_3_1(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(processing token)
@@ -533,7 +533,7 @@ async def test_normal_3_1(self, processor, db, personal_info_contract):
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
token_2.token_status = 0
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -638,9 +638,9 @@ async def test_normal_3_1(self, processor, db, personal_info_contract):
assert _transfer.source_event == IDXTransferSourceEventType.TRANSFER.value
assert _transfer.data is None
block = web3.eth.get_block(tx_receipt_1["blockNumber"])
- assert _transfer.block_timestamp == datetime.utcfromtimestamp(
- block["timestamp"]
- )
+ assert _transfer.block_timestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
_transfer = _transfer_list[1]
assert _transfer.id == 2
@@ -652,9 +652,9 @@ async def test_normal_3_1(self, processor, db, personal_info_contract):
assert _transfer.source_event == IDXTransferSourceEventType.TRANSFER.value
assert _transfer.data is None
block = web3.eth.get_block(tx_receipt_2["blockNumber"])
- assert _transfer.block_timestamp == datetime.utcfromtimestamp(
- block["timestamp"]
- )
+ assert _transfer.block_timestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
_transfer = _transfer_list[2]
assert _transfer.id == 3
@@ -666,9 +666,9 @@ async def test_normal_3_1(self, processor, db, personal_info_contract):
assert _transfer.source_event == IDXTransferSourceEventType.UNLOCK.value
assert _transfer.data == {"message": "unlock"}
block = web3.eth.get_block(tx_receipt_3["blockNumber"])
- assert _transfer.block_timestamp == datetime.utcfromtimestamp(
- block["timestamp"]
- )
+ assert _transfer.block_timestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
_transfer = _transfer_list[3]
assert _transfer.id == 4
@@ -680,9 +680,9 @@ async def test_normal_3_1(self, processor, db, personal_info_contract):
assert _transfer.source_event == IDXTransferSourceEventType.UNLOCK.value
assert _transfer.data == {"message": "unlock"}
block = web3.eth.get_block(tx_receipt_4["blockNumber"])
- assert _transfer.block_timestamp == datetime.utcfromtimestamp(
- block["timestamp"]
- )
+ assert _transfer.block_timestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
_idx_transfer_block_number = db.scalars(
select(IDXTransferBlockNumber).limit(1)
@@ -740,7 +740,7 @@ async def test_normal_3_2(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -828,9 +828,9 @@ async def test_normal_3_2(self, processor, db, personal_info_contract):
assert _transfer.amount == value_list1[i]
assert _transfer.source_event == IDXTransferSourceEventType.TRANSFER.value
assert _transfer.data is None
- assert _transfer.block_timestamp == datetime.utcfromtimestamp(
- block["timestamp"]
- )
+ assert _transfer.block_timestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
block = web3.eth.get_block(tx_receipt_2["blockNumber"])
for i in range(0, 4):
@@ -843,9 +843,9 @@ async def test_normal_3_2(self, processor, db, personal_info_contract):
assert _transfer.amount == value_list2[i]
assert _transfer.source_event == IDXTransferSourceEventType.TRANSFER.value
assert _transfer.data is None
- assert _transfer.block_timestamp == datetime.utcfromtimestamp(
- block["timestamp"]
- )
+ assert _transfer.block_timestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
_idx_transfer_block_number = db.scalars(
select(IDXTransferBlockNumber).limit(1)
@@ -885,7 +885,7 @@ async def test_normal_4(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token2
@@ -900,7 +900,7 @@ async def test_normal_4(self, processor, db, personal_info_contract):
token_2.issuer_address = issuer_address
token_2.abi = token_contract_2.abi
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -970,9 +970,9 @@ async def test_normal_4(self, processor, db, personal_info_contract):
assert _transfer.source_event == IDXTransferSourceEventType.TRANSFER.value
assert _transfer.data is None
block = web3.eth.get_block(tx_receipt_1["blockNumber"])
- assert _transfer.block_timestamp == datetime.utcfromtimestamp(
- block["timestamp"]
- )
+ assert _transfer.block_timestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
_transfer = _transfer_list[1]
assert _transfer.id == 2
assert _transfer.transaction_hash == tx_hash_2
@@ -983,9 +983,9 @@ async def test_normal_4(self, processor, db, personal_info_contract):
assert _transfer.source_event == IDXTransferSourceEventType.TRANSFER.value
assert _transfer.data is None
block = web3.eth.get_block(tx_receipt_2["blockNumber"])
- assert _transfer.block_timestamp == datetime.utcfromtimestamp(
- block["timestamp"]
- )
+ assert _transfer.block_timestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
_transfer = _transfer_list[2]
assert _transfer.id == 3
@@ -997,9 +997,9 @@ async def test_normal_4(self, processor, db, personal_info_contract):
assert _transfer.source_event == IDXTransferSourceEventType.TRANSFER.value
assert _transfer.data is None
block = web3.eth.get_block(tx_receipt_3["blockNumber"])
- assert _transfer.block_timestamp == datetime.utcfromtimestamp(
- block["timestamp"]
- )
+ assert _transfer.block_timestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
_transfer = _transfer_list[3]
assert _transfer.id == 4
@@ -1011,9 +1011,9 @@ async def test_normal_4(self, processor, db, personal_info_contract):
assert _transfer.source_event == IDXTransferSourceEventType.TRANSFER.value
assert _transfer.data is None
block = web3.eth.get_block(tx_receipt_4["blockNumber"])
- assert _transfer.block_timestamp == datetime.utcfromtimestamp(
- block["timestamp"]
- )
+ assert _transfer.block_timestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
_idx_transfer_block_number = db.scalars(
select(IDXTransferBlockNumber).limit(1)
@@ -1079,7 +1079,7 @@ async def test_normal_6(
token_1.issuer_address = issuer_address
token_1.abi = token_contract1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -1105,7 +1105,7 @@ async def test_normal_6(
token_2.issuer_address = issuer_address
token_2.abi = token_contract2.abi
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -1155,7 +1155,7 @@ async def test_error_1(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
diff --git a/tests/test_batch_indexer_transfer_approval.py b/tests/batch/test_indexer_transfer_approval.py
similarity index 87%
rename from tests/test_batch_indexer_transfer_approval.py
rename to tests/batch/test_indexer_transfer_approval.py
index d90704ec..d2039461 100644
--- a/tests/test_batch_indexer_transfer_approval.py
+++ b/tests/batch/test_indexer_transfer_approval.py
@@ -18,7 +18,7 @@
"""
import logging
-from datetime import datetime
+from datetime import UTC, datetime
from unittest import mock
from unittest.mock import patch
from uuid import UUID
@@ -55,7 +55,7 @@
from batch.indexer_transfer_approval import LOG, Processor, main
from config import CHAIN_ID, TX_GAS_LIMIT
from tests.account_config import config_eth_account
-from tests.utils.contract_utils import (
+from tests.contract_utils import (
IbetSecurityTokenContractTestUtils as STContractUtils,
IbetSecurityTokenEscrowContractTestUtils as STEscrowContractUtils,
PersonalInfoContractTestUtils,
@@ -177,7 +177,7 @@ async def test_normal_1_1(self, processor, db, personal_info_contract):
token_1.abi = "abi"
token_1.tx_hash = "tx_hash"
token_1.token_status = 0
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -224,7 +224,7 @@ async def test_normal_1_2(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(processing token)
@@ -235,7 +235,7 @@ async def test_normal_1_2(self, processor, db, personal_info_contract):
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
token_2.token_status = 0
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : BlockNumber
@@ -300,7 +300,7 @@ async def test_normal_2_1(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(processing token)
@@ -311,7 +311,7 @@ async def test_normal_2_1(self, processor, db, personal_info_contract):
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
token_2.token_status = 0
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : BlockNumber
@@ -364,10 +364,9 @@ async def test_normal_2_1(self, processor, db, personal_info_contract):
assert _transfer_approval.amount == 30
assert _transfer_approval.application_datetime is None
block = web3.eth.get_block(tx_receipt_1["blockNumber"])
- assert (
- _transfer_approval.application_blocktimestamp
- == datetime.utcfromtimestamp(block["timestamp"])
- )
+ assert _transfer_approval.application_blocktimestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
assert _transfer_approval.approval_datetime is None
assert _transfer_approval.approval_blocktimestamp is None
assert _transfer_approval.cancellation_blocktimestamp is None
@@ -434,7 +433,7 @@ async def test_normal_2_2_1(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : BlockNumber
@@ -501,16 +500,14 @@ async def test_normal_2_2_1(self, processor, db, personal_info_contract):
assert _transfer_approval.to_address == issuer_address
assert _transfer_approval.amount == 30
assert _transfer_approval.application_datetime is None
- assert (
- _transfer_approval.application_blocktimestamp
- == datetime.utcfromtimestamp(block_2["timestamp"])
- )
+ assert _transfer_approval.application_blocktimestamp == datetime.fromtimestamp(
+ block_2["timestamp"], UTC
+ ).replace(tzinfo=None)
assert _transfer_approval.approval_datetime is None
assert _transfer_approval.approval_blocktimestamp is None
- assert (
- _transfer_approval.cancellation_blocktimestamp
- == datetime.utcfromtimestamp(block_3["timestamp"])
- )
+ assert _transfer_approval.cancellation_blocktimestamp == datetime.fromtimestamp(
+ block_3["timestamp"], UTC
+ ).replace(tzinfo=None)
assert _transfer_approval.cancelled is True
assert _transfer_approval.transfer_approved is None
@@ -574,7 +571,7 @@ async def test_normal_2_2_2(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : BlockNumber
@@ -641,16 +638,14 @@ async def test_normal_2_2_2(self, processor, db, personal_info_contract):
assert _transfer_approval.to_address == issuer_address
assert _transfer_approval.amount == 30
assert _transfer_approval.application_datetime is None
- assert (
- _transfer_approval.application_blocktimestamp
- == datetime.utcfromtimestamp(block_2["timestamp"])
- )
+ assert _transfer_approval.application_blocktimestamp == datetime.fromtimestamp(
+ block_2["timestamp"], UTC
+ ).replace(tzinfo=None)
assert _transfer_approval.approval_datetime is None
assert _transfer_approval.approval_blocktimestamp is None
- assert (
- _transfer_approval.cancellation_blocktimestamp
- == datetime.utcfromtimestamp(block_3["timestamp"])
- )
+ assert _transfer_approval.cancellation_blocktimestamp == datetime.fromtimestamp(
+ block_3["timestamp"], UTC
+ ).replace(tzinfo=None)
assert _transfer_approval.cancelled is True
assert _transfer_approval.transfer_approved is None
@@ -713,7 +708,7 @@ async def test_normal_2_3(self, processor, db, personal_info_contract):
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : BlockNumber
@@ -751,7 +746,7 @@ async def test_normal_2_3(self, processor, db, personal_info_contract):
block_1 = web3.eth.get_block(tx_receipt_1["blockNumber"])
# ApproveTransfer from issuer
- now = datetime.utcnow()
+ now = datetime.now(UTC).replace(tzinfo=None)
tx = token_contract_1.functions.approveTransfer(
0, str(now.timestamp())
).build_transaction(
@@ -781,15 +776,14 @@ async def test_normal_2_3(self, processor, db, personal_info_contract):
assert _transfer_approval.to_address == issuer_address
assert _transfer_approval.amount == 30
assert _transfer_approval.application_datetime is None
- assert (
- _transfer_approval.application_blocktimestamp
- == datetime.utcfromtimestamp(block_1["timestamp"])
- )
+ assert _transfer_approval.application_blocktimestamp == datetime.fromtimestamp(
+ block_1["timestamp"], UTC
+ ).replace(tzinfo=None)
assert _transfer_approval.approval_datetime == now
block_2 = web3.eth.get_block(tx_receipt_2["blockNumber"])
- assert _transfer_approval.approval_blocktimestamp == datetime.utcfromtimestamp(
- block_2["timestamp"]
- )
+ assert _transfer_approval.approval_blocktimestamp == datetime.fromtimestamp(
+ block_2["timestamp"], UTC
+ ).replace(tzinfo=None)
assert _transfer_approval.cancellation_blocktimestamp is None
assert _transfer_approval.cancelled is None
assert _transfer_approval.transfer_approved is True
@@ -858,7 +852,7 @@ async def test_normal_2_4(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : BlockNumber
@@ -894,7 +888,7 @@ async def test_normal_2_4(
ContractUtils.send_transaction(tx, user_private_key_1)
# ApplyForTransfer
- now = datetime.utcnow()
+ now = datetime.now(UTC).replace(tzinfo=None)
tx = ibet_security_token_escrow_contract.functions.createEscrow(
token_address_1,
user_address_2,
@@ -932,10 +926,9 @@ async def test_normal_2_4(
assert _transfer_approval.amount == 30
assert _transfer_approval.application_datetime == now
block = web3.eth.get_block(tx_receipt_1["blockNumber"])
- assert (
- _transfer_approval.application_blocktimestamp
- == datetime.utcfromtimestamp(block["timestamp"])
- )
+ assert _transfer_approval.application_blocktimestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
assert _transfer_approval.approval_datetime is None
assert _transfer_approval.approval_blocktimestamp is None
assert _transfer_approval.cancellation_blocktimestamp is None
@@ -1006,7 +999,7 @@ async def test_normal_2_5(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : Token(processing token)
@@ -1017,7 +1010,7 @@ async def test_normal_2_5(
token_2.abi = "abi"
token_2.tx_hash = "tx_hash"
token_2.token_status = 0
- token_2.version = TokenVersion.V_23_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
# Prepare data : BlockNumber
@@ -1099,16 +1092,14 @@ async def test_normal_2_5(
assert _transfer_approval.to_address == user_address_2
assert _transfer_approval.amount == 30
assert _transfer_approval.application_datetime is None
- assert (
- _transfer_approval.application_blocktimestamp
- == datetime.utcfromtimestamp(block_1["timestamp"])
- )
+ assert _transfer_approval.application_blocktimestamp == datetime.fromtimestamp(
+ block_1["timestamp"], UTC
+ ).replace(tzinfo=None)
assert _transfer_approval.approval_datetime is None
assert _transfer_approval.approval_blocktimestamp is None
- assert (
- _transfer_approval.cancellation_blocktimestamp
- == datetime.utcfromtimestamp(block_2["timestamp"])
- )
+ assert _transfer_approval.cancellation_blocktimestamp == datetime.fromtimestamp(
+ block_2["timestamp"], UTC
+ ).replace(tzinfo=None)
assert _transfer_approval.cancelled is True
assert _transfer_approval.transfer_approved is None
@@ -1177,7 +1168,7 @@ async def test_normal_2_6(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : BlockNumber
@@ -1258,10 +1249,9 @@ async def test_normal_2_6(
assert _transfer_approval.to_address == user_address_2
assert _transfer_approval.amount == 30
assert _transfer_approval.application_datetime is None
- assert (
- _transfer_approval.application_blocktimestamp
- == datetime.utcfromtimestamp(block_1["timestamp"])
- )
+ assert _transfer_approval.application_blocktimestamp == datetime.fromtimestamp(
+ block_1["timestamp"], UTC
+ ).replace(tzinfo=None)
assert _transfer_approval.approval_datetime is None
assert _transfer_approval.approval_blocktimestamp is None
assert _transfer_approval.cancellation_blocktimestamp is None
@@ -1332,7 +1322,7 @@ async def test_normal_2_7(
token_1.issuer_address = issuer_address
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : BlockNumber
@@ -1427,14 +1417,13 @@ async def test_normal_2_7(
assert _transfer_approval.to_address == user_address_2
assert _transfer_approval.amount == 30
assert _transfer_approval.application_datetime is None
- assert (
- _transfer_approval.application_blocktimestamp
- == datetime.utcfromtimestamp(block["timestamp"])
- )
+ assert _transfer_approval.application_blocktimestamp == datetime.fromtimestamp(
+ block["timestamp"], UTC
+ ).replace(tzinfo=None)
assert _transfer_approval.approval_datetime is None
- assert _transfer_approval.approval_blocktimestamp == datetime.utcfromtimestamp(
- block_2["timestamp"]
- )
+ assert _transfer_approval.approval_blocktimestamp == datetime.fromtimestamp(
+ block_2["timestamp"], UTC
+ ).replace(tzinfo=None)
assert _transfer_approval.cancellation_blocktimestamp is None
assert _transfer_approval.cancelled is None
assert _transfer_approval.transfer_approved is True
@@ -1480,182 +1469,9 @@ async def test_normal_3(
)
#
- # If DB session fails in sinking phase each event, batch outputs a log "exception occurred".
- @pytest.mark.asyncio
- async def test_normal_4(
- self,
- processor,
- db,
- personal_info_contract,
- ibet_security_token_escrow_contract,
- caplog: pytest.LogCaptureFixture,
- ):
- user_1 = config_eth_account("user1")
- issuer_address = user_1["address"]
- issuer_private_key = decode_keyfile_json(
- raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
- )
- user_2 = config_eth_account("user2")
- user_address_1 = user_2["address"]
- user_pk_1 = decode_keyfile_json(
- raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
- )
- user_3 = config_eth_account("user3")
- user_address_2 = user_3["address"]
- user_pk_2 = decode_keyfile_json(
- raw_keyfile_json=user_3["keyfile_json"], password="password".encode("utf-8")
- )
-
- # Prepare data : Account
- account = Account()
- account.issuer_address = issuer_address
- account.keyfile = user_1["keyfile_json"]
- account.eoa_password = E2EEUtils.encrypt("password")
- db.add(account)
-
- # Prepare data : Token
- token_contract = await deploy_bond_token_contract(
- issuer_address,
- issuer_private_key,
- personal_info_contract.address,
- tradable_exchange_contract_address=ibet_security_token_escrow_contract.address,
- transfer_approval_required=True,
- )
- token_address = token_contract.address
- token = Token()
- token.type = TokenType.IBET_STRAIGHT_BOND.value
- token.token_address = token_address
- token.issuer_address = issuer_address
- token.abi = token_contract.abi
- token.tx_hash = "tx_hash"
- token.version = TokenVersion.V_23_12
- db.add(token)
- db.commit()
-
- PersonalInfoContractTestUtils.register(
- personal_info_contract.address,
- user_address_1,
- user_pk_1,
- [issuer_address, ""],
- )
- PersonalInfoContractTestUtils.register(
- personal_info_contract.address,
- user_address_2,
- user_pk_2,
- [issuer_address, ""],
- )
- PersonalInfoContractTestUtils.register(
- personal_info_contract.address,
- issuer_address,
- issuer_private_key,
- [issuer_address, ""],
- )
- PersonalInfoContractTestUtils.register(
- personal_info_contract.address,
- issuer_address,
- issuer_private_key,
- [ibet_security_token_escrow_contract.address, ""],
- )
-
- STContractUtils.set_transfer_approve_required(
- token_contract.address, issuer_address, issuer_private_key, [True]
- )
- STContractUtils.apply_for_transfer(
- token_contract.address,
- issuer_address,
- issuer_private_key,
- [user_address_1, 10, "to user1#1"],
- )
- STContractUtils.apply_for_transfer(
- token_contract.address,
- issuer_address,
- issuer_private_key,
- [user_address_1, 20, "to user1#2"],
- )
- STContractUtils.apply_for_transfer(
- token_contract.address,
- issuer_address,
- issuer_private_key,
- [user_address_2, 10, "to user2#1"],
- )
-
- STContractUtils.cancel_transfer(
- token_contract.address,
- issuer_address,
- issuer_private_key,
- [0, "to user1#1"],
- )
- STContractUtils.approve_transfer(
- token_contract.address,
- issuer_address,
- issuer_private_key,
- [1, "to user1#2"],
- )
- STContractUtils.approve_transfer(
- token_contract.address,
- issuer_address,
- issuer_private_key,
- [2, "to user2#1"],
- )
-
- STContractUtils.set_transfer_approve_required(
- token_contract.address, issuer_address, issuer_private_key, [False]
- )
- STContractUtils.transfer(
- token_contract.address,
- user_address_1,
- user_pk_1,
- [ibet_security_token_escrow_contract.address, 20],
- )
- STContractUtils.set_transfer_approve_required(
- token_contract.address, issuer_address, issuer_private_key, [True]
- )
-
- STEscrowContractUtils.create_escrow(
- ibet_security_token_escrow_contract.address,
- user_address_1,
- user_pk_1,
- [token_contract.address, user_address_2, 10, issuer_address, "", ""],
- )
- latest_security_escrow_id = STEscrowContractUtils.get_latest_escrow_id(
- ibet_security_token_escrow_contract.address
- )
-
- STEscrowContractUtils.finish_escrow(
- ibet_security_token_escrow_contract.address,
- issuer_address,
- issuer_private_key,
- [latest_security_escrow_id],
- )
- STEscrowContractUtils.approve_transfer(
- ibet_security_token_escrow_contract.address,
- issuer_address,
- issuer_private_key,
- [latest_security_escrow_id, ""],
- )
-
- with caplog.at_level(logging.ERROR, LOG.name), patch.object(
- Session, "add", side_effect=Exception()
- ):
- # Then execute processor.
- await processor.sync_new_logs()
-
- # Error occurs in events with exception of Escrow.
- assert (
- caplog.record_tuples.count(
- (
- LOG.name,
- logging.ERROR,
- "An exception occurred during event synchronization",
- )
- )
- == 3
- )
-
- #
# Newly tokens added
@pytest.mark.asyncio
- async def test_normal_5(
+ async def test_normal_4(
self,
processor: Processor,
db: Session,
@@ -1691,7 +1507,7 @@ async def test_normal_5(
token_1.issuer_address = issuer_address
token_1.abi = token_contract1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -1718,7 +1534,7 @@ async def test_normal_5(
token_2.issuer_address = issuer_address
token_2.abi = token_contract2.abi
token_2.tx_hash = "tx_hash"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
db.commit()
@@ -1769,7 +1585,7 @@ async def test_error_1(
token.issuer_address = issuer_address
token.abi = token_contract.abi
token.tx_hash = "tx_hash"
- token.version = TokenVersion.V_23_12
+ token.version = TokenVersion.V_24_06
db.add(token)
db.commit()
diff --git a/tests/test_batch_processor_batch_issue_redeem.py b/tests/batch/test_processor_batch_issue_redeem.py
similarity index 100%
rename from tests/test_batch_processor_batch_issue_redeem.py
rename to tests/batch/test_processor_batch_issue_redeem.py
diff --git a/tests/test_batch_processor_bulk_transfer.py b/tests/batch/test_processor_bulk_transfer.py
similarity index 100%
rename from tests/test_batch_processor_bulk_transfer.py
rename to tests/batch/test_processor_bulk_transfer.py
diff --git a/tests/test_batch_processor_create_utxo.py b/tests/batch/test_processor_create_utxo.py
similarity index 98%
rename from tests/test_batch_processor_create_utxo.py
rename to tests/batch/test_processor_create_utxo.py
index 8dd58620..bc366864 100644
--- a/tests/test_batch_processor_create_utxo.py
+++ b/tests/batch/test_processor_create_utxo.py
@@ -26,7 +26,7 @@
from eth_keyfile import decode_keyfile_json
from sqlalchemy import select
from web3 import Web3
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
from app.model.blockchain import IbetShareContract, IbetStraightBondContract
from app.model.blockchain.tx_params.ibet_share import (
@@ -50,14 +50,14 @@
from batch.processor_create_utxo import Processor
from config import CHAIN_ID, TX_GAS_LIMIT, WEB3_HTTP_PROVIDER
from tests.account_config import config_eth_account
-from tests.utils.contract_utils import (
+from tests.contract_utils import (
IbetExchangeContractTestUtils,
IbetSecurityTokenContractTestUtils as STContractUtils,
PersonalInfoContractTestUtils,
)
web3 = Web3(Web3.HTTPProvider(WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
@pytest.fixture(scope="function")
@@ -153,7 +153,7 @@ async def test_normal_1(self, mock_func, processor, db):
_token_1.issuer_address = issuer_address
_token_1.token_address = token_address_1
_token_1.abi = {}
- _token_1.version = TokenVersion.V_23_12
+ _token_1.version = TokenVersion.V_24_06
db.add(_token_1)
token_address_2 = await deploy_share_token_contract(
@@ -165,7 +165,7 @@ async def test_normal_1(self, mock_func, processor, db):
_token_2.issuer_address = issuer_address
_token_2.token_address = token_address_2
_token_2.abi = {}
- _token_2.version = TokenVersion.V_22_12
+ _token_2.version = TokenVersion.V_24_06
db.add(_token_2)
account = Account()
@@ -300,7 +300,7 @@ async def test_normal_2(self, mock_func, processor, db):
_token_1.issuer_address = issuer_address
_token_1.token_address = token_address_1
_token_1.abi = {}
- _token_1.version = TokenVersion.V_23_12
+ _token_1.version = TokenVersion.V_24_06
db.add(_token_1)
latest_block_number = web3.eth.block_number
@@ -418,7 +418,7 @@ async def test_normal_3(self, mock_func, processor, db):
_token_1.issuer_address = issuer_address
_token_1.token_address = token_address_1
_token_1.abi = {}
- _token_1.version = TokenVersion.V_23_12
+ _token_1.version = TokenVersion.V_24_06
db.add(_token_1)
account = Account()
@@ -515,7 +515,7 @@ async def test_normal_4(self, mock_func, processor, db):
_token_1.issuer_address = issuer_address
_token_1.token_address = token_address_1
_token_1.abi = {}
- _token_1.version = TokenVersion.V_23_12
+ _token_1.version = TokenVersion.V_24_06
db.add(_token_1)
account = Account()
@@ -606,7 +606,7 @@ async def test_normal_5(
_token_1.issuer_address = issuer_address
_token_1.token_address = token_address_1
_token_1.abi = {}
- _token_1.version = TokenVersion.V_23_12
+ _token_1.version = TokenVersion.V_24_06
db.add(_token_1)
PersonalInfoContractTestUtils.register(
@@ -791,7 +791,7 @@ async def test_normal_6(self, mock_func, processor, db):
_token_1.issuer_address = issuer_address
_token_1.token_address = token_address_1
_token_1.abi = {}
- _token_1.version = TokenVersion.V_23_12
+ _token_1.version = TokenVersion.V_24_06
db.add(_token_1)
token_address_2 = await deploy_share_token_contract(
@@ -803,7 +803,7 @@ async def test_normal_6(self, mock_func, processor, db):
_token_2.issuer_address = issuer_address
_token_2.token_address = token_address_2
_token_2.abi = {}
- _token_2.version = TokenVersion.V_22_12
+ _token_2.version = TokenVersion.V_24_06
db.add(_token_2)
account = Account()
@@ -879,7 +879,7 @@ async def test_normal_7(self, mock_func, processor, db):
_token_1.issuer_address = issuer_address
_token_1.token_address = token_address_1
_token_1.abi = {}
- _token_1.version = TokenVersion.V_23_12
+ _token_1.version = TokenVersion.V_24_06
db.add(_token_1)
token_address_2 = await deploy_share_token_contract(
@@ -891,7 +891,7 @@ async def test_normal_7(self, mock_func, processor, db):
_token_2.issuer_address = issuer_address
_token_2.token_address = token_address_2
_token_2.abi = {}
- _token_2.version = TokenVersion.V_22_12
+ _token_2.version = TokenVersion.V_24_06
db.add(_token_2)
account = Account()
@@ -1038,7 +1038,7 @@ async def test_normal_8_1(self, mock_func, processor, db):
_token_1.issuer_address = issuer_address
_token_1.token_address = token_address_1
_token_1.abi = {}
- _token_1.version = TokenVersion.V_23_12
+ _token_1.version = TokenVersion.V_24_06
db.add(_token_1)
token_address_2 = await deploy_share_token_contract(
@@ -1050,7 +1050,7 @@ async def test_normal_8_1(self, mock_func, processor, db):
_token_2.issuer_address = issuer_address
_token_2.token_address = token_address_2
_token_2.abi = {}
- _token_2.version = TokenVersion.V_22_12
+ _token_2.version = TokenVersion.V_24_06
db.add(_token_2)
account = Account()
@@ -1231,7 +1231,7 @@ async def test_normal_8_2(self, mock_func, processor, db):
_token_1.issuer_address = issuer_address
_token_1.token_address = token_address_1
_token_1.abi = {}
- _token_1.version = TokenVersion.V_23_12
+ _token_1.version = TokenVersion.V_24_06
db.add(_token_1)
token_address_2 = await deploy_share_token_contract(
@@ -1243,7 +1243,7 @@ async def test_normal_8_2(self, mock_func, processor, db):
_token_2.issuer_address = issuer_address
_token_2.token_address = token_address_2
_token_2.abi = {}
- _token_2.version = TokenVersion.V_22_12
+ _token_2.version = TokenVersion.V_24_06
db.add(_token_2)
account = Account()
@@ -1409,7 +1409,7 @@ async def test_normal_9(self, mock_func, processor, db):
_token_1.issuer_address = issuer_address
_token_1.token_address = token_address_1
_token_1.abi = {}
- _token_1.version = TokenVersion.V_23_12
+ _token_1.version = TokenVersion.V_24_06
db.add(_token_1)
account = Account()
@@ -1545,7 +1545,7 @@ async def test_error_1(self, processor, db):
_token_1.issuer_address = issuer_address
_token_1.token_address = token_address_1
_token_1.abi = {}
- _token_1.version = TokenVersion.V_23_12
+ _token_1.version = TokenVersion.V_24_06
db.add(_token_1)
db.commit()
diff --git a/tests/test_batch_processor_generate_rsa_key.py b/tests/batch/test_processor_generate_rsa_key.py
similarity index 100%
rename from tests/test_batch_processor_generate_rsa_key.py
rename to tests/batch/test_processor_generate_rsa_key.py
diff --git a/tests/test_batch_processor_modify_personal_info.py b/tests/batch/test_processor_modify_personal_info.py
similarity index 98%
rename from tests/test_batch_processor_modify_personal_info.py
rename to tests/batch/test_processor_modify_personal_info.py
index 779bf13a..5580cf01 100644
--- a/tests/test_batch_processor_modify_personal_info.py
+++ b/tests/batch/test_processor_modify_personal_info.py
@@ -21,7 +21,7 @@
from eth_keyfile import decode_keyfile_json
from sqlalchemy import func, select
from web3 import Web3
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
from app.model.blockchain import (
IbetShareContract,
@@ -50,7 +50,7 @@
from tests.account_config import config_eth_account
web3 = Web3(Web3.HTTPProvider(WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
@pytest.fixture(scope="function")
@@ -214,7 +214,7 @@ async def test_normal_1(self, processor, db):
token_1.issuer_address = issuer_address_1
token_1.token_address = token_contract_address_1
token_1.abi = "abi"
- token_1.version = TokenVersion.V_23_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
personal_info_contract_address_2 = deploy_personal_info_contract(user_1)
@@ -227,7 +227,7 @@ async def test_normal_1(self, processor, db):
token_2.issuer_address = issuer_address_1
token_2.token_address = token_contract_address_2
token_2.abi = "abi"
- token_2.version = TokenVersion.V_22_12
+ token_2.version = TokenVersion.V_24_06
db.add(token_2)
token_contract_address_3 = await deploy_bond_token_contract(user_1, None)
@@ -237,7 +237,7 @@ async def test_normal_1(self, processor, db):
token_3.issuer_address = issuer_address_1
token_3.token_address = token_contract_address_3
token_3.abi = "abi"
- token_3.version = TokenVersion.V_23_12
+ token_3.version = TokenVersion.V_24_06
db.add(token_3)
token_contract_address_4 = await deploy_share_token_contract(user_1, None)
@@ -247,7 +247,7 @@ async def test_normal_1(self, processor, db):
token_4.issuer_address = issuer_address_1
token_4.token_address = token_contract_address_4
token_4.abi = "abi"
- token_4.version = TokenVersion.V_22_12
+ token_4.version = TokenVersion.V_24_06
db.add(token_4)
# PersonalInfo
diff --git a/tests/test_batch_processor_monitor_block_sync.py b/tests/batch/test_processor_monitor_block_sync.py
similarity index 98%
rename from tests/test_batch_processor_monitor_block_sync.py
rename to tests/batch/test_processor_monitor_block_sync.py
index ba89d8bd..e2830226 100644
--- a/tests/test_batch_processor_monitor_block_sync.py
+++ b/tests/batch/test_processor_monitor_block_sync.py
@@ -23,14 +23,14 @@
import pytest
from sqlalchemy import select
from web3 import Web3
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
from app.model.db import Node
from batch.processor_monitor_block_sync import Processor
from config import WEB3_HTTP_PROVIDER
web3 = Web3(Web3.HTTPProvider(WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
@pytest.fixture(scope="function")
diff --git a/tests/test_batch_processor_register_personal_info.py b/tests/batch/test_processor_register_personal_info.py
similarity index 99%
rename from tests/test_batch_processor_register_personal_info.py
rename to tests/batch/test_processor_register_personal_info.py
index bce9501b..b76baff2 100644
--- a/tests/test_batch_processor_register_personal_info.py
+++ b/tests/batch/test_processor_register_personal_info.py
@@ -170,7 +170,7 @@ async def test_normal_1(
token_1.issuer_address = _account["address"]
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
db.commit()
@@ -215,7 +215,7 @@ async def test_normal_2(
token_1.issuer_address = _account["address"]
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : BatchRegisterPersonalInfoUpload
@@ -318,7 +318,7 @@ async def test_normal_3(
token_1.issuer_address = _account["address"]
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : BatchRegisterPersonalInfoUpload
@@ -477,7 +477,7 @@ async def test_normal_4(
token_1.issuer_address = _account["address"]
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : BatchRegisterPersonalInfoUpload
@@ -617,7 +617,7 @@ async def test_error_1(
token_1.issuer_address = _account["address"]
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : BatchRegisterPersonalInfoUpload
@@ -732,7 +732,7 @@ async def test_error_2(
token_1.issuer_address = _account["address"]
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : BatchRegisterPersonalInfoUpload
@@ -865,7 +865,7 @@ async def test_error_3(
token_1.issuer_address = _account["address"]
token_1.abi = token_contract_1.abi
token_1.tx_hash = "tx_hash"
- token_1.version = TokenVersion.V_22_12
+ token_1.version = TokenVersion.V_24_06
db.add(token_1)
# Prepare data : BatchRegisterPersonalInfoUpload
diff --git a/tests/test_batch_processor_rotate_e2e_messaging_rsa_key.py b/tests/batch/test_processor_rotate_e2e_messaging_rsa_key.py
similarity index 97%
rename from tests/test_batch_processor_rotate_e2e_messaging_rsa_key.py
rename to tests/batch/test_processor_rotate_e2e_messaging_rsa_key.py
index 5341d357..23e9b112 100644
--- a/tests/test_batch_processor_rotate_e2e_messaging_rsa_key.py
+++ b/tests/batch/test_processor_rotate_e2e_messaging_rsa_key.py
@@ -19,7 +19,7 @@
import logging
import time
-from datetime import datetime, timedelta, timezone
+from datetime import UTC, datetime, timedelta
from unittest import mock
from unittest.mock import ANY, call
@@ -104,7 +104,7 @@ async def test_normal_1_2(self, processor, db):
_rsa_key_1.rsa_private_key = "rsa_private_key_1"
_rsa_key_1.rsa_public_key = "rsa_public_key_1"
_rsa_key_1.rsa_passphrase = "rsa_passphrase_1"
- _rsa_key_1.block_timestamp = datetime.utcnow()
+ _rsa_key_1.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key_1)
db.commit()
@@ -149,7 +149,7 @@ async def test_normal_1_3(self, processor, db):
_rsa_key_1.rsa_private_key = "rsa_private_key_1"
_rsa_key_1.rsa_public_key = "rsa_public_key_1"
_rsa_key_1.rsa_passphrase = "rsa_passphrase_1"
- _rsa_key_1.block_timestamp = datetime.utcnow()
+ _rsa_key_1.block_timestamp = datetime.now(UTC).replace(tzinfo=None)
db.add(_rsa_key_1)
db.commit()
@@ -199,7 +199,7 @@ async def test_normal_2(self, processor, db, e2e_messaging_contract):
_account.rsa_generation = 2
db.add(_account)
- datetime_now = datetime.utcnow()
+ datetime_now = datetime.now(UTC).replace(tzinfo=None)
# Prepare data : E2EMessagingAccountRsaKey
_rsa_key_1_1 = E2EMessagingAccountRsaKey()
@@ -270,13 +270,13 @@ async def test_normal_2(self, processor, db, e2e_messaging_contract):
{
"number": 12345,
"timestamp": datetime(
- 2099, 4, 27, 12, 34, 56, tzinfo=timezone.utc
+ 2099, 4, 27, 12, 34, 56, tzinfo=UTC
).timestamp(),
},
{
"number": 12350,
"timestamp": datetime(
- 2099, 4, 27, 12, 34, 59, tzinfo=timezone.utc
+ 2099, 4, 27, 12, 34, 59, tzinfo=UTC
).timestamp(),
},
],
@@ -380,7 +380,7 @@ async def test_error_1(self, processor, db):
_account.rsa_generation = 2
db.add(_account)
- datetime_now = datetime.utcnow()
+ datetime_now = datetime.now(UTC).replace(tzinfo=None)
# Prepare data : E2EMessagingAccountRsaKey
_rsa_key = E2EMessagingAccountRsaKey()
@@ -425,7 +425,7 @@ async def test_error_2(self, processor, db, e2e_messaging_contract):
_account.rsa_generation = 2
db.add(_account)
- datetime_now = datetime.utcnow()
+ datetime_now = datetime.now(UTC).replace(tzinfo=None)
# Prepare data : E2EMessagingAccountRsaKey
_rsa_key = E2EMessagingAccountRsaKey()
@@ -491,7 +491,7 @@ async def test_error_3(
_account.rsa_generation = 2
db.add(_account)
- datetime_now = datetime.utcnow()
+ datetime_now = datetime.now(UTC).replace(tzinfo=None)
# Prepare data : E2EMessagingAccountRsaKey
_rsa_key = E2EMessagingAccountRsaKey()
diff --git a/tests/test_batch_processor_scheduled_events.py b/tests/batch/test_processor_scheduled_events.py
similarity index 96%
rename from tests/test_batch_processor_scheduled_events.py
rename to tests/batch/test_processor_scheduled_events.py
index 25725ba9..b6c727b6 100644
--- a/tests/test_batch_processor_scheduled_events.py
+++ b/tests/batch/test_processor_scheduled_events.py
@@ -18,7 +18,7 @@
"""
import logging
-from datetime import datetime, timedelta, timezone
+from datetime import UTC, datetime, timedelta
from unittest.mock import patch
import pytest
@@ -76,11 +76,11 @@ async def test_normal_1(self, processor, db):
db.add(account)
# prepare data : ScheduledEvents
- datetime_past_utc = datetime.now(timezone.utc) + timedelta(days=-1)
+ datetime_past_utc = datetime.now(UTC) + timedelta(days=-1)
datetime_past_str = datetime_past_utc.isoformat()
- datetime_now_utc = datetime.now(timezone.utc)
+ datetime_now_utc = datetime.now(UTC)
datetime_now_str = datetime_now_utc.isoformat()
- datetime_pending_utc = datetime.now(timezone.utc) + timedelta(days=1)
+ datetime_pending_utc = datetime.now(UTC) + timedelta(days=1)
datetime_pending_str = datetime_pending_utc.isoformat()
update_data = {
"face_value": 10000,
@@ -98,6 +98,7 @@ async def test_normal_1(self, processor, db):
"is_redeemed": True,
"tradable_exchange_contract_address": "0xe883A6f441Ad5682d37DF31d34fc012bcB07A740",
"personal_info_contract_address": "0xa4CEe3b909751204AA151860ebBE8E7A851c2A1a",
+ "require_personal_info_registered": False,
"contact_information": "問い合わせ先test",
"privacy_policy": "プライバシーポリシーtest",
"is_canceled": False,
@@ -186,6 +187,7 @@ async def test_normal_1(self, processor, db):
"is_offering": False,
"is_redeemed": True,
"personal_info_contract_address": "0xa4CEe3b909751204AA151860ebBE8E7A851c2A1a",
+ "require_personal_info_registered": False,
"privacy_policy": "プライバシーポリシーtest",
"redemption_value": 11000,
"status": False,
@@ -217,11 +219,11 @@ async def test_normal_2(self, processor, db):
db.add(account)
# prepare data : ScheduledEvents
- datetime_past_utc = datetime.now(timezone.utc) + timedelta(days=-1)
+ datetime_past_utc = datetime.now(UTC) + timedelta(days=-1)
datetime_past_str = datetime_past_utc.isoformat()
- datetime_now_utc = datetime.now(timezone.utc)
+ datetime_now_utc = datetime.now(UTC)
datetime_now_str = datetime_now_utc.isoformat()
- datetime_pending_utc = datetime.now(timezone.utc) + timedelta(days=1)
+ datetime_pending_utc = datetime.now(UTC) + timedelta(days=1)
datetime_pending_str = datetime_pending_utc.isoformat()
update_data = {
@@ -231,6 +233,7 @@ async def test_normal_2(self, processor, db):
"dividend_payment_date": "20211231",
"tradable_exchange_contract_address": "0xe883A6f441Ad5682d37DF31d34fc012bcB07A740",
"personal_info_contract_address": "0xa4CEe3b909751204AA151860ebBE8E7A851c2A1a",
+ "require_personal_info_registered": False,
"image_url": [
"http://sampleurl.com/some_image1.png",
"http://sampleurl.com/some_image2.png",
@@ -328,6 +331,7 @@ async def test_normal_2(self, processor, db):
"is_canceled": False,
"is_offering": False,
"personal_info_contract_address": "0xa4CEe3b909751204AA151860ebBE8E7A851c2A1a",
+ "require_personal_info_registered": False,
"privacy_policy": "プライバシーポリシーtest",
"status": False,
"tradable_exchange_contract_address": "0xe883A6f441Ad5682d37DF31d34fc012bcB07A740",
@@ -352,7 +356,7 @@ async def test_error_1(self, processor, db):
_token_address = "token_address_test"
# prepare data : ScheduledEvents
- datetime_now_utc = datetime.now(timezone.utc)
+ datetime_now_utc = datetime.now(UTC)
datetime_now_str = datetime_now_utc.isoformat()
update_data = {}
@@ -408,7 +412,7 @@ async def test_error_2(self, processor, db):
db.add(account)
# prepare data : ScheduledEvents
- datetime_now_utc = datetime.now(timezone.utc)
+ datetime_now_utc = datetime.now(UTC)
datetime_now_str = datetime_now_utc.isoformat()
update_data = {}
@@ -466,7 +470,7 @@ async def test_error_3(self, processor, db):
db.add(account)
# prepare data : ScheduledEvents
- datetime_now_utc = datetime.now(timezone.utc)
+ datetime_now_utc = datetime.now(UTC)
datetime_now_str = datetime_now_utc.isoformat()
update_data = {}
@@ -535,7 +539,7 @@ async def test_error_4(self, processor, db):
db.add(account)
# prepare data : ScheduledEvents
- datetime_now_jtc = datetime.now(timezone.utc)
+ datetime_now_jtc = datetime.now(UTC)
datetime_now_str = datetime_now_jtc.isoformat()
update_data = {}
@@ -606,7 +610,7 @@ async def test_error_5(self, processor, db, caplog):
db.add(account)
# prepare data : ScheduledEvents
- datetime_now_utc = datetime.now(timezone.utc)
+ datetime_now_utc = datetime.now(UTC)
datetime_now_str = datetime_now_utc.isoformat()
update_data = {}
@@ -686,7 +690,7 @@ async def test_error_6(self, processor, db, caplog):
db.add(account)
# prepare data : ScheduledEvents
- datetime_now_jtc = datetime.now(timezone.utc)
+ datetime_now_jtc = datetime.now(UTC)
datetime_now_str = datetime_now_jtc.isoformat()
update_data = {}
diff --git a/tests/test_batch_processor_update_token.py b/tests/batch/test_processor_update_token.py
similarity index 98%
rename from tests/test_batch_processor_update_token.py
rename to tests/batch/test_processor_update_token.py
index a8519a2e..0287066c 100644
--- a/tests/test_batch_processor_update_token.py
+++ b/tests/batch/test_processor_update_token.py
@@ -17,7 +17,7 @@
SPDX-License-Identifier: Apache-2.0
"""
-from datetime import datetime, timezone
+from datetime import UTC, datetime
from unittest.mock import ANY, call, patch
import pytest
@@ -84,7 +84,7 @@ async def test_normal_1(self, processor, db):
_token_1.token_address = _token_address_1
_token_1.abi = ""
_token_1.token_status = 0
- _token_1.version = TokenVersion.V_22_12
+ _token_1.version = TokenVersion.V_24_06
db.add(_token_1)
_update_token_1 = UpdateToken()
@@ -102,6 +102,7 @@ async def test_normal_1(self, processor, db):
"cancellation_date": "20221231",
"tradable_exchange_contract_address": "0x0000000000000000000000000000000000000001", # update
"personal_info_contract_address": "0x0000000000000000000000000000000000000002", # update
+ "require_personal_info_registered": False, # update
"transferable": False, # update
"status": False, # update
"is_offering": True, # update
@@ -124,7 +125,7 @@ async def test_normal_1(self, processor, db):
_token_2.token_address = _token_address_2
_token_2.abi = ""
_token_2.token_status = 0
- _token_2.version = TokenVersion.V_23_12
+ _token_2.version = TokenVersion.V_24_06
db.add(_token_2)
_update_token_2 = UpdateToken()
@@ -149,6 +150,7 @@ async def test_normal_1(self, processor, db):
"is_redeemed": True, # update
"tradable_exchange_contract_address": "0x0000000000000000000000000000000000000001", # update
"personal_info_contract_address": "0x0000000000000000000000000000000000000002", # update
+ "require_personal_info_registered": False, # update
"contact_information": "contact info test", # update
"privacy_policy": "privacy policy test", # update
"transfer_approval_required": True, # update
@@ -181,9 +183,7 @@ async def test_normal_1(self, processor, db):
mock_block = {
"number": 12345,
- "timestamp": datetime(
- 2021, 4, 27, 12, 34, 56, tzinfo=timezone.utc
- ).timestamp(),
+ "timestamp": datetime(2021, 4, 27, 12, 34, 56, tzinfo=UTC).timestamp(),
}
with patch(
target="app.model.blockchain.token.IbetShareContract.update",
@@ -210,6 +210,7 @@ async def test_normal_1(self, processor, db):
dividends=None,
tradable_exchange_contract_address="0x0000000000000000000000000000000000000001",
personal_info_contract_address="0x0000000000000000000000000000000000000002",
+ require_personal_info_registered=False,
transferable=False,
status=False,
is_offering=True,
@@ -232,6 +233,7 @@ async def test_normal_1(self, processor, db):
is_redeemed=True,
tradable_exchange_contract_address="0x0000000000000000000000000000000000000001",
personal_info_contract_address="0x0000000000000000000000000000000000000002",
+ require_personal_info_registered=False,
contact_information="contact info test",
privacy_policy="privacy policy test",
transfer_approval_required=True,
@@ -363,7 +365,7 @@ async def test_error_1(self, processor, db):
_token_1.token_address = _token_address_1
_token_1.abi = ""
_token_1.token_status = 0
- _token_1.version = TokenVersion.V_22_12
+ _token_1.version = TokenVersion.V_24_06
db.add(_token_1)
_update_token_1 = UpdateToken()
@@ -401,7 +403,7 @@ async def test_error_1(self, processor, db):
_token_2.token_address = _token_address_2
_token_2.abi = ""
_token_2.token_status = 0
- _token_2.version = TokenVersion.V_23_12
+ _token_2.version = TokenVersion.V_24_06
db.add(_token_2)
_update_token_2 = UpdateToken()
@@ -580,7 +582,7 @@ async def test_error_2(self, processor, db):
_token_1.token_address = _token_address_1
_token_1.abi = ""
_token_1.token_status = 0
- _token_1.version = TokenVersion.V_22_12
+ _token_1.version = TokenVersion.V_24_06
db.add(_token_1)
_update_token_1 = UpdateToken()
@@ -618,7 +620,7 @@ async def test_error_2(self, processor, db):
_token_2.token_address = _token_address_2
_token_2.abi = ""
_token_2.token_status = 0
- _token_2.version = TokenVersion.V_23_12
+ _token_2.version = TokenVersion.V_24_06
db.add(_token_2)
_update_token_2 = UpdateToken()
@@ -797,7 +799,7 @@ async def test_error_3(self, processor, db):
_token_1.token_address = _token_address_1
_token_1.abi = ""
_token_1.token_status = 0
- _token_1.version = TokenVersion.V_22_12
+ _token_1.version = TokenVersion.V_24_06
db.add(_token_1)
_update_token_1 = UpdateToken()
@@ -835,7 +837,7 @@ async def test_error_3(self, processor, db):
_token_2.token_address = _token_address_2
_token_2.abi = ""
_token_2.token_status = 0
- _token_2.version = TokenVersion.V_23_12
+ _token_2.version = TokenVersion.V_24_06
db.add(_token_2)
_update_token_2 = UpdateToken()
@@ -1021,7 +1023,7 @@ async def test_error_4(self, processor, db):
_token_1.token_address = _token_address_1
_token_1.abi = ""
_token_1.token_status = 0
- _token_1.version = TokenVersion.V_22_12
+ _token_1.version = TokenVersion.V_24_06
db.add(_token_1)
_update_token_1 = UpdateToken()
@@ -1059,7 +1061,7 @@ async def test_error_4(self, processor, db):
_token_2.token_address = _token_address_2
_token_2.abi = ""
_token_2.token_status = 0
- _token_2.version = TokenVersion.V_23_12
+ _token_2.version = TokenVersion.V_24_06
db.add(_token_2)
_update_token_2 = UpdateToken()
diff --git a/tests/conftest.py b/tests/conftest.py
index 1aa577b4..c1fc02d4 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -24,7 +24,7 @@
from httpx import AsyncClient
from sqlalchemy import text
from web3 import Web3
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
from web3.types import RPCEndpoint
from app.database import (
@@ -40,7 +40,7 @@
from tests.account_config import config_eth_account
web3 = Web3(Web3.HTTPProvider(WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
@pytest_asyncio.fixture(scope="session")
@@ -298,6 +298,44 @@ def ibet_security_token_escrow_contract():
return ContractUtils.get_contract("IbetSecurityTokenEscrow", contract_address)
+@pytest.fixture(scope="function")
+def ibet_security_token_dvp_contract():
+ user_1 = config_eth_account("user1")
+ deployer_address = user_1["address"]
+ deployer_private_key = decode_keyfile_json(
+ raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
+ )
+
+ # Deploy storage contract
+ storage_contract_address, _, _ = ContractUtils.deploy_contract(
+ "DVPStorage", [], deployer_address, deployer_private_key
+ )
+
+ # Deploy security token DVP contract
+ contract_address, _, _ = ContractUtils.deploy_contract(
+ "IbetSecurityTokenDVP",
+ [storage_contract_address],
+ deployer_address,
+ deployer_private_key,
+ )
+
+ # Upgrade version
+ storage_contract = ContractUtils.get_contract(
+ "DVPStorage", storage_contract_address
+ )
+ tx = storage_contract.functions.upgradeVersion(contract_address).build_transaction(
+ {
+ "chainId": CHAIN_ID,
+ "from": deployer_address,
+ "gas": TX_GAS_LIMIT,
+ "gasPrice": 0,
+ }
+ )
+ ContractUtils.send_transaction(tx, deployer_private_key)
+
+ return ContractUtils.get_contract("IbetSecurityTokenDVP", contract_address)
+
+
@pytest.fixture(scope="function")
def e2e_messaging_contract():
user_1 = config_eth_account("user1")
diff --git a/tests/utils/contract_utils.py b/tests/contract_utils.py
similarity index 70%
rename from tests/utils/contract_utils.py
rename to tests/contract_utils.py
index 0401c0a2..3c1171f5 100644
--- a/tests/utils/contract_utils.py
+++ b/tests/contract_utils.py
@@ -20,13 +20,13 @@
from typing import Dict
from web3 import Web3
-from web3.middleware import geth_poa_middleware
+from web3.middleware import ExtraDataToPOAMiddleware
from app.utils.contract_utils import ContractUtils
from config import CHAIN_ID, TX_GAS_LIMIT, WEB3_HTTP_PROVIDER
web3 = Web3(Web3.HTTPProvider(WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
+web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
"""
Helper Methods for Contract Testing
@@ -385,3 +385,155 @@ def get_latest_escrow_id(contract_address: str):
contract_name="IbetSecurityTokenEscrow", contract_address=contract_address
)
return escrow_contract.functions.latestEscrowId().call()
+
+
+class IbetSecurityTokenDVPContractTestUtils:
+ @staticmethod
+ def balance_of(contract_address: str, account_address: str, token_address: str):
+ dvp_contract = ContractUtils.get_contract(
+ contract_name="IbetSecurityTokenDVP", contract_address=contract_address
+ )
+ return dvp_contract.functions.balanceOf(account_address, token_address).call()
+
+ @staticmethod
+ def create_delivery(
+ contract_address: str, tx_from: str, private_key: str, args: list
+ ):
+ dvp_contract = ContractUtils.get_contract(
+ contract_name="IbetSecurityTokenDVP", contract_address=contract_address
+ )
+ tx = dvp_contract.functions.createDelivery(*args).build_transaction(
+ {"chainId": CHAIN_ID, "from": tx_from, "gas": TX_GAS_LIMIT, "gasPrice": 0}
+ )
+ ContractUtils.send_transaction(transaction=tx, private_key=private_key)
+
+ @staticmethod
+ def cancel_delivery(
+ contract_address: str, tx_from: str, private_key: str, args: list
+ ):
+ dvp_contract = ContractUtils.get_contract(
+ contract_name="IbetSecurityTokenDVP", contract_address=contract_address
+ )
+ tx = dvp_contract.functions.cancelDelivery(*args).build_transaction(
+ {"chainId": CHAIN_ID, "from": tx_from, "gas": TX_GAS_LIMIT, "gasPrice": 0}
+ )
+ ContractUtils.send_transaction(transaction=tx, private_key=private_key)
+
+ @staticmethod
+ def confirm_delivery(
+ contract_address: str, tx_from: str, private_key: str, args: list
+ ):
+ dvp_contract = ContractUtils.get_contract(
+ contract_name="IbetSecurityTokenDVP", contract_address=contract_address
+ )
+ tx = dvp_contract.functions.confirmDelivery(*args).build_transaction(
+ {"chainId": CHAIN_ID, "from": tx_from, "gas": TX_GAS_LIMIT, "gasPrice": 0}
+ )
+ ContractUtils.send_transaction(transaction=tx, private_key=private_key)
+
+ @staticmethod
+ def finish_delivery(
+ contract_address: str, tx_from: str, private_key: str, args: list
+ ):
+ dvp_contract = ContractUtils.get_contract(
+ contract_name="IbetSecurityTokenDVP", contract_address=contract_address
+ )
+ tx = dvp_contract.functions.finishDelivery(*args).build_transaction(
+ {"chainId": CHAIN_ID, "from": tx_from, "gas": TX_GAS_LIMIT, "gasPrice": 0}
+ )
+ ContractUtils.send_transaction(transaction=tx, private_key=private_key)
+
+ @staticmethod
+ def abort_delivery(
+ contract_address: str, tx_from: str, private_key: str, args: list
+ ):
+ dvp_contract = ContractUtils.get_contract(
+ contract_name="IbetSecurityTokenDVP", contract_address=contract_address
+ )
+ tx = dvp_contract.functions.abortDelivery(*args).build_transaction(
+ {"chainId": CHAIN_ID, "from": tx_from, "gas": TX_GAS_LIMIT, "gasPrice": 0}
+ )
+ ContractUtils.send_transaction(transaction=tx, private_key=private_key)
+
+ @staticmethod
+ def get_latest_delivery_id(contract_address: str):
+ escrow_contract = ContractUtils.get_contract(
+ contract_name="IbetSecurityTokenDVP", contract_address=contract_address
+ )
+ return escrow_contract.functions.latestDeliveryId().call()
+
+
+class IbetSecurityTokenDVPContractTestUtils:
+ @staticmethod
+ def balance_of(contract_address: str, account_address: str, token_address: str):
+ dvp_contract = ContractUtils.get_contract(
+ contract_name="IbetSecurityTokenDVP", contract_address=contract_address
+ )
+ return dvp_contract.functions.balanceOf(account_address, token_address).call()
+
+ @staticmethod
+ def create_delivery(
+ contract_address: str, tx_from: str, private_key: str, args: list
+ ):
+ dvp_contract = ContractUtils.get_contract(
+ contract_name="IbetSecurityTokenDVP", contract_address=contract_address
+ )
+ tx = dvp_contract.functions.createDelivery(*args).build_transaction(
+ {"chainId": CHAIN_ID, "from": tx_from, "gas": TX_GAS_LIMIT, "gasPrice": 0}
+ )
+ ContractUtils.send_transaction(transaction=tx, private_key=private_key)
+
+ @staticmethod
+ def cancel_delivery(
+ contract_address: str, tx_from: str, private_key: str, args: list
+ ):
+ dvp_contract = ContractUtils.get_contract(
+ contract_name="IbetSecurityTokenDVP", contract_address=contract_address
+ )
+ tx = dvp_contract.functions.cancelDelivery(*args).build_transaction(
+ {"chainId": CHAIN_ID, "from": tx_from, "gas": TX_GAS_LIMIT, "gasPrice": 0}
+ )
+ ContractUtils.send_transaction(transaction=tx, private_key=private_key)
+
+ @staticmethod
+ def confirm_delivery(
+ contract_address: str, tx_from: str, private_key: str, args: list
+ ):
+ dvp_contract = ContractUtils.get_contract(
+ contract_name="IbetSecurityTokenDVP", contract_address=contract_address
+ )
+ tx = dvp_contract.functions.confirmDelivery(*args).build_transaction(
+ {"chainId": CHAIN_ID, "from": tx_from, "gas": TX_GAS_LIMIT, "gasPrice": 0}
+ )
+ ContractUtils.send_transaction(transaction=tx, private_key=private_key)
+
+ @staticmethod
+ def finish_delivery(
+ contract_address: str, tx_from: str, private_key: str, args: list
+ ):
+ dvp_contract = ContractUtils.get_contract(
+ contract_name="IbetSecurityTokenDVP", contract_address=contract_address
+ )
+ tx = dvp_contract.functions.finishDelivery(*args).build_transaction(
+ {"chainId": CHAIN_ID, "from": tx_from, "gas": TX_GAS_LIMIT, "gasPrice": 0}
+ )
+ ContractUtils.send_transaction(transaction=tx, private_key=private_key)
+
+ @staticmethod
+ def abort_delivery(
+ contract_address: str, tx_from: str, private_key: str, args: list
+ ):
+ dvp_contract = ContractUtils.get_contract(
+ contract_name="IbetSecurityTokenDVP", contract_address=contract_address
+ )
+ tx = dvp_contract.functions.abortDelivery(*args).build_transaction(
+ {"chainId": CHAIN_ID, "from": tx_from, "gas": TX_GAS_LIMIT, "gasPrice": 0}
+ )
+ ContractUtils.send_transaction(transaction=tx, private_key=private_key)
+
+ @staticmethod
+ def get_latest_delivery_id(contract_address: str):
+ escrow_contract = ContractUtils.get_contract(
+ contract_name="IbetSecurityTokenDVP", contract_address=contract_address
+ )
+ return escrow_contract.functions.latestDeliveryId().call()
diff --git a/tests/test_app_routers_bond_transfers_{token_address}_GET.py b/tests/test_app_routers_bond_transfers_{token_address}_GET.py
deleted file mode 100644
index 0c16d570..00000000
--- a/tests/test_app_routers_bond_transfers_{token_address}_GET.py
+++ /dev/null
@@ -1,1267 +0,0 @@
-"""
-Copyright BOOSTRY Co., Ltd.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-
-You may obtain a copy of the License at
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-
-See the License for the specific language governing permissions and
-limitations under the License.
-
-SPDX-License-Identifier: Apache-2.0
-"""
-
-from datetime import datetime
-
-from pytz import timezone
-
-import config
-from app.model.db import (
- IDXPersonalInfo,
- IDXTransfer,
- IDXTransferSourceEventType,
- Token,
- TokenType,
- TokenVersion,
-)
-
-local_tz = timezone(config.TZ)
-
-
-class TestAppRoutersBondTransfersGET:
- # target API endpoint
- base_url = "/bond/transfers/{}"
-
- test_transaction_hash = "test_transaction_hash"
- test_issuer_address = "test_issuer_address"
- test_token_address = "test_token_address"
- test_from_address = "test_from_address"
- test_to_address = "test_to_address"
- test_block_timestamp = [
- datetime.strptime("2022/01/02 15:20:30", "%Y/%m/%d %H:%M:%S"), # JST 2022/01/03
- datetime.strptime("2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"), # JST 2022/01/02
- datetime.strptime("2022/01/02 00:20:30", "%Y/%m/%d %H:%M:%S"), # JST 2022/01/02
- ]
- test_block_timestamp_str = [
- "2022-01-03T00:20:30+09:00",
- "2022-01-02T00:20:30+09:00",
- "2022-01-02T09:20:30+09:00",
- ]
-
- ###########################################################################
- # Normal Case
- ###########################################################################
-
- #
- # default sort
- def test_normal_1(self, client, db):
- # prepare data: Token
- _token = Token()
- _token.type = TokenType.IBET_STRAIGHT_BOND.value
- _token.tx_hash = self.test_transaction_hash
- _token.issuer_address = self.test_issuer_address
- _token.token_address = self.test_token_address
- _token.abi = {}
- _token.version = TokenVersion.V_23_12
- db.add(_token)
-
- # prepare data: IDXTransfer
- for i in range(0, 3):
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = self.test_from_address
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = i
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[i]
- db.add(_idx_transfer)
-
- db.commit()
-
- # request target API
- resp = client.get(self.base_url.format(self.test_token_address))
-
- # assertion
- assert resp.status_code == 200
- assumed_response = {
- "result_set": {"count": 3, "offset": None, "limit": None, "total": 3},
- "transfer_history": [
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": None,
- "to_address": self.test_to_address,
- "to_address_personal_information": None,
- "amount": 0,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[0],
- },
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": None,
- "to_address": self.test_to_address,
- "to_address_personal_information": None,
- "amount": 2,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[2],
- },
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": None,
- "to_address": self.test_to_address,
- "to_address_personal_information": None,
- "amount": 1,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[1],
- },
- ],
- }
- assert resp.json() == assumed_response
-
- #
- # offset, limit
- def test_normal_2_1(self, client, db):
- # prepare data: Token
- _token = Token()
- _token.type = TokenType.IBET_STRAIGHT_BOND.value
- _token.tx_hash = self.test_transaction_hash
- _token.issuer_address = self.test_issuer_address
- _token.token_address = self.test_token_address
- _token.abi = {}
- _token.version = TokenVersion.V_23_12
- db.add(_token)
-
- # prepare data: IDXPersonalInfo
- _personal_info_from = IDXPersonalInfo()
- _personal_info_from.account_address = self.test_from_address
- _personal_info_from.issuer_address = self.test_issuer_address
- _personal_info_from._personal_info = {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_from)
-
- _personal_info_to = IDXPersonalInfo()
- _personal_info_to.account_address = self.test_to_address
- _personal_info_to.issuer_address = self.test_issuer_address
- _personal_info_to._personal_info = {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- "birth": "birth_test2",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_to)
-
- # prepare data: IDXTransfer
- for i in range(0, 3):
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = self.test_from_address
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = i
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[i]
- db.add(_idx_transfer)
-
- db.commit()
-
- # request target API
- resp = client.get(
- self.base_url.format(self.test_token_address) + "?offset=1&limit=1"
- )
-
- # assertion
- assert resp.status_code == 200
- assumed_response = {
- "result_set": {"count": 3, "offset": 1, "limit": 1, "total": 3},
- "transfer_history": [
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": {
- "address": "address_test1",
- "birth": "birth_test1",
- "email": "email_test1",
- "is_corporate": False,
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "tax_category": 10,
- },
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 2,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[2],
- },
- ],
- }
- assert resp.json() == assumed_response
-
- #
- # filter: source_event
- def test_normal_2_2(self, client, db):
- # prepare data: Token
- _token = Token()
- _token.type = TokenType.IBET_STRAIGHT_BOND.value
- _token.tx_hash = self.test_transaction_hash
- _token.issuer_address = self.test_issuer_address
- _token.token_address = self.test_token_address
- _token.abi = {}
- _token.version = TokenVersion.V_23_12
- db.add(_token)
-
- # prepare data: IDXPersonalInfo
- _personal_info_from = IDXPersonalInfo()
- _personal_info_from.account_address = self.test_from_address
- _personal_info_from.issuer_address = self.test_issuer_address
- _personal_info_from._personal_info = {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_from)
-
- _personal_info_to = IDXPersonalInfo()
- _personal_info_to.account_address = self.test_to_address
- _personal_info_to.issuer_address = self.test_issuer_address
- _personal_info_to._personal_info = {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- "birth": "birth_test2",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_to)
-
- # prepare data: IDXTransfer
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = "test_from_address_2"
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 0
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[0]
- db.add(_idx_transfer)
-
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = "test_from_address_2"
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 1
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[1]
- db.add(_idx_transfer)
-
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = "test_from_address_1"
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 2
- _idx_transfer.source_event = IDXTransferSourceEventType.UNLOCK.value
- _idx_transfer.data = {"message": "unlock"}
- _idx_transfer.block_timestamp = self.test_block_timestamp[2]
- db.add(_idx_transfer)
-
- db.commit()
-
- # request target API
- resp = client.get(
- self.base_url.format(self.test_token_address),
- params={"source_event": IDXTransferSourceEventType.UNLOCK.value},
- )
-
- # assertion
- assert resp.status_code == 200
- assumed_response = {
- "result_set": {"count": 1, "offset": None, "limit": None, "total": 3},
- "transfer_history": [
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": "test_from_address_1",
- "from_address_personal_information": None,
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 2,
- "source_event": IDXTransferSourceEventType.UNLOCK.value,
- "data": {"message": "unlock"},
- "block_timestamp": self.test_block_timestamp_str[2],
- }
- ],
- }
- assert resp.json() == assumed_response
-
- #
- # filter: data
- def test_normal_2_3(self, client, db):
- # prepare data: Token
- _token = Token()
- _token.type = TokenType.IBET_STRAIGHT_BOND.value
- _token.tx_hash = self.test_transaction_hash
- _token.issuer_address = self.test_issuer_address
- _token.token_address = self.test_token_address
- _token.abi = {}
- _token.version = TokenVersion.V_23_12
- db.add(_token)
-
- # prepare data: IDXPersonalInfo
- _personal_info_from = IDXPersonalInfo()
- _personal_info_from.account_address = self.test_from_address
- _personal_info_from.issuer_address = self.test_issuer_address
- _personal_info_from._personal_info = {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_from)
-
- _personal_info_to = IDXPersonalInfo()
- _personal_info_to.account_address = self.test_to_address
- _personal_info_to.issuer_address = self.test_issuer_address
- _personal_info_to._personal_info = {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- "birth": "birth_test2",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_to)
-
- # prepare data: IDXTransfer
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = "test_from_address_2"
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 0
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[0]
- db.add(_idx_transfer)
-
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = "test_from_address_2"
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 1
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[1]
- db.add(_idx_transfer)
-
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = "test_from_address_1"
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 2
- _idx_transfer.source_event = IDXTransferSourceEventType.UNLOCK.value
- _idx_transfer.data = {"message": "unlock"}
- _idx_transfer.block_timestamp = self.test_block_timestamp[2]
- db.add(_idx_transfer)
-
- db.commit()
-
- # request target API
- resp = client.get(
- self.base_url.format(self.test_token_address), params={"data": "unlo"}
- )
-
- # assertion
- assert resp.status_code == 200
- assumed_response = {
- "result_set": {"count": 1, "offset": None, "limit": None, "total": 3},
- "transfer_history": [
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": "test_from_address_1",
- "from_address_personal_information": None,
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 2,
- "source_event": IDXTransferSourceEventType.UNLOCK.value,
- "data": {"message": "unlock"},
- "block_timestamp": self.test_block_timestamp_str[2],
- }
- ],
- }
- assert resp.json() == assumed_response
-
- #
- # sort: block_timestamp ASC
- def test_normal_3(self, client, db):
- # prepare data: Token
- _token = Token()
- _token.type = TokenType.IBET_STRAIGHT_BOND.value
- _token.tx_hash = self.test_transaction_hash
- _token.issuer_address = self.test_issuer_address
- _token.token_address = self.test_token_address
- _token.abi = {}
- _token.version = TokenVersion.V_23_12
- db.add(_token)
-
- # prepare data: IDXPersonalInfo
- _personal_info_from = IDXPersonalInfo()
- _personal_info_from.account_address = self.test_from_address
- _personal_info_from.issuer_address = self.test_issuer_address
- _personal_info_from._personal_info = {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_from)
-
- _personal_info_to = IDXPersonalInfo()
- _personal_info_to.account_address = self.test_to_address
- _personal_info_to.issuer_address = self.test_issuer_address
- _personal_info_to._personal_info = {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- "birth": "birth_test2",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_to)
-
- # prepare data: IDXTransfer
- for i in range(0, 3):
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = self.test_from_address
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = i
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[i]
- db.add(_idx_transfer)
-
- db.commit()
-
- # request target API
- resp = client.get(
- self.base_url.format(self.test_token_address),
- params={
- "sort_item": "block_timestamp",
- "sort_order": 0,
- },
- )
-
- # assertion
- assert resp.status_code == 200
- assumed_response = {
- "result_set": {"count": 3, "offset": None, "limit": None, "total": 3},
- "transfer_history": [
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": {
- "address": "address_test1",
- "birth": "birth_test1",
- "email": "email_test1",
- "is_corporate": False,
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "tax_category": 10,
- },
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 1,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[1],
- },
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": {
- "address": "address_test1",
- "birth": "birth_test1",
- "email": "email_test1",
- "is_corporate": False,
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "tax_category": 10,
- },
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 2,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[2],
- },
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": {
- "address": "address_test1",
- "birth": "birth_test1",
- "email": "email_test1",
- "is_corporate": False,
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "tax_category": 10,
- },
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 0,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[0],
- },
- ],
- }
- assert resp.json() == assumed_response
-
- #
- # sort: from_address ASC
- def test_normal_4(self, client, db):
- # prepare data: Token
- _token = Token()
- _token.type = TokenType.IBET_STRAIGHT_BOND.value
- _token.tx_hash = self.test_transaction_hash
- _token.issuer_address = self.test_issuer_address
- _token.token_address = self.test_token_address
- _token.abi = {}
- _token.version = TokenVersion.V_23_12
- db.add(_token)
-
- # prepare data: IDXPersonalInfo
- _personal_info_from = IDXPersonalInfo()
- _personal_info_from.account_address = self.test_from_address
- _personal_info_from.issuer_address = self.test_issuer_address
- _personal_info_from._personal_info = {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_from)
-
- _personal_info_to = IDXPersonalInfo()
- _personal_info_to.account_address = self.test_to_address
- _personal_info_to.issuer_address = self.test_issuer_address
- _personal_info_to._personal_info = {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- "birth": "birth_test2",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_to)
-
- # prepare data: IDXTransfer
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = "test_from_address_2"
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 0
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[0]
- db.add(_idx_transfer)
-
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = "test_from_address_2"
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 1
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[1]
- db.add(_idx_transfer)
-
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = "test_from_address_1"
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 2
- _idx_transfer.source_event = IDXTransferSourceEventType.UNLOCK.value
- _idx_transfer.data = {"message": "unlock"}
- _idx_transfer.block_timestamp = self.test_block_timestamp[2]
- db.add(_idx_transfer)
-
- db.commit()
-
- # request target API
- resp = client.get(
- self.base_url.format(self.test_token_address),
- params={
- "sort_item": "from_address",
- "sort_order": 0,
- },
- )
-
- # assertion
- assert resp.status_code == 200
- assumed_response = {
- "result_set": {"count": 3, "offset": None, "limit": None, "total": 3},
- "transfer_history": [
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": "test_from_address_1",
- "from_address_personal_information": None,
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 2,
- "source_event": IDXTransferSourceEventType.UNLOCK.value,
- "data": {"message": "unlock"},
- "block_timestamp": self.test_block_timestamp_str[2],
- },
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": "test_from_address_2",
- "from_address_personal_information": None,
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 0,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[0],
- },
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": "test_from_address_2",
- "from_address_personal_information": None,
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 1,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[1],
- },
- ],
- }
- assert resp.json() == assumed_response
-
- #
- # sort: to_address DESC
- def test_normal_5(self, client, db):
- # prepare data: Token
- _token = Token()
- _token.type = TokenType.IBET_STRAIGHT_BOND.value
- _token.tx_hash = self.test_transaction_hash
- _token.issuer_address = self.test_issuer_address
- _token.token_address = self.test_token_address
- _token.abi = {}
- _token.version = TokenVersion.V_23_12
- db.add(_token)
-
- # prepare data: IDXPersonalInfo
- _personal_info_from = IDXPersonalInfo()
- _personal_info_from.account_address = self.test_from_address
- _personal_info_from.issuer_address = self.test_issuer_address
- _personal_info_from._personal_info = {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_from)
-
- _personal_info_to = IDXPersonalInfo()
- _personal_info_to.account_address = self.test_to_address
- _personal_info_to.issuer_address = self.test_issuer_address
- _personal_info_to._personal_info = {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- "birth": "birth_test2",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_to)
-
- # prepare data: IDXTransfer
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = self.test_from_address
- _idx_transfer.to_address = "test_to_address_2"
- _idx_transfer.amount = 0
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[0]
- db.add(_idx_transfer)
-
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = self.test_from_address
- _idx_transfer.to_address = "test_to_address_1"
- _idx_transfer.amount = 1
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[1]
- db.add(_idx_transfer)
-
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = self.test_from_address
- _idx_transfer.to_address = "test_to_address_1"
- _idx_transfer.amount = 2
- _idx_transfer.source_event = IDXTransferSourceEventType.UNLOCK.value
- _idx_transfer.data = {"message": "unlock"}
- _idx_transfer.block_timestamp = self.test_block_timestamp[2]
- db.add(_idx_transfer)
-
- db.commit()
-
- # request target API
- resp = client.get(
- self.base_url.format(self.test_token_address),
- params={
- "sort_item": "to_address",
- "sort_order": 1,
- },
- )
-
- # assertion
- assert resp.status_code == 200
- assumed_response = {
- "result_set": {"count": 3, "offset": None, "limit": None, "total": 3},
- "transfer_history": [
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": {
- "address": "address_test1",
- "birth": "birth_test1",
- "email": "email_test1",
- "is_corporate": False,
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "tax_category": 10,
- },
- "to_address": "test_to_address_2",
- "to_address_personal_information": None,
- "amount": 0,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[0],
- },
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": {
- "address": "address_test1",
- "birth": "birth_test1",
- "email": "email_test1",
- "is_corporate": False,
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "tax_category": 10,
- },
- "to_address": "test_to_address_1",
- "to_address_personal_information": None,
- "amount": 2,
- "source_event": IDXTransferSourceEventType.UNLOCK.value,
- "data": {"message": "unlock"},
- "block_timestamp": self.test_block_timestamp_str[2],
- },
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": {
- "address": "address_test1",
- "birth": "birth_test1",
- "email": "email_test1",
- "is_corporate": False,
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "tax_category": 10,
- },
- "to_address": "test_to_address_1",
- "to_address_personal_information": None,
- "amount": 1,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[1],
- },
- ],
- }
- assert resp.json() == assumed_response
-
- #
- # sort: amount DESC
- def test_normal_6(self, client, db):
- # prepare data: Token
- _token = Token()
- _token.type = TokenType.IBET_STRAIGHT_BOND.value
- _token.tx_hash = self.test_transaction_hash
- _token.issuer_address = self.test_issuer_address
- _token.token_address = self.test_token_address
- _token.abi = {}
- _token.version = TokenVersion.V_23_12
- db.add(_token)
-
- # prepare data: IDXPersonalInfo
- _personal_info_from = IDXPersonalInfo()
- _personal_info_from.account_address = self.test_from_address
- _personal_info_from.issuer_address = self.test_issuer_address
- _personal_info_from._personal_info = {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_from)
-
- _personal_info_to = IDXPersonalInfo()
- _personal_info_to.account_address = self.test_to_address
- _personal_info_to.issuer_address = self.test_issuer_address
- _personal_info_to._personal_info = {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- "birth": "birth_test2",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_to)
-
- # prepare data: IDXTransfer
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = self.test_from_address
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 1
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[0]
- db.add(_idx_transfer)
-
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = self.test_from_address
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 2
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[1]
- db.add(_idx_transfer)
-
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = self.test_from_address
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 2
- _idx_transfer.source_event = IDXTransferSourceEventType.UNLOCK.value
- _idx_transfer.data = {"message": "unlock"}
- _idx_transfer.block_timestamp = self.test_block_timestamp[2]
- db.add(_idx_transfer)
-
- db.commit()
-
- # request target API
- resp = client.get(
- self.base_url.format(self.test_token_address),
- params={
- "sort_item": "amount",
- "sort_order": 0,
- },
- )
-
- # assertion
- assert resp.status_code == 200
- assumed_response = {
- "result_set": {"count": 3, "offset": None, "limit": None, "total": 3},
- "transfer_history": [
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": {
- "address": "address_test1",
- "birth": "birth_test1",
- "email": "email_test1",
- "is_corporate": False,
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "tax_category": 10,
- },
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 1,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[0],
- },
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": {
- "address": "address_test1",
- "birth": "birth_test1",
- "email": "email_test1",
- "is_corporate": False,
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "tax_category": 10,
- },
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 2,
- "source_event": IDXTransferSourceEventType.UNLOCK.value,
- "data": {"message": "unlock"},
- "block_timestamp": self.test_block_timestamp_str[2],
- },
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": {
- "address": "address_test1",
- "birth": "birth_test1",
- "email": "email_test1",
- "is_corporate": False,
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "tax_category": 10,
- },
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 2,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[1],
- },
- ],
- }
- assert resp.json() == assumed_response
-
- ###########################################################################
- # Error Case
- ###########################################################################
-
- #
- # token not found
- def test_error_1(self, client, db):
- # request target API
- resp = client.get(self.base_url.format(self.test_token_address))
-
- # assertion
- assert resp.status_code == 404
- assumed_response = {
- "meta": {"code": 1, "title": "NotFound"},
- "detail": "token not found",
- }
- assert resp.json() == assumed_response
-
- #
- # processing token
- def test_error_2(self, client, db):
- # prepare data: Token
- _token = Token()
- _token.type = TokenType.IBET_STRAIGHT_BOND.value
- _token.tx_hash = self.test_transaction_hash
- _token.issuer_address = self.test_issuer_address
- _token.token_address = self.test_token_address
- _token.abi = {}
- _token.token_status = 0
- _token.version = TokenVersion.V_23_12
- db.add(_token)
-
- db.commit()
-
- # request target API
- resp = client.get(self.base_url.format(self.test_token_address))
-
- # assertion
- assert resp.status_code == 400
- assert resp.json() == {
- "meta": {"code": 1, "title": "InvalidParameterError"},
- "detail": "this token is temporarily unavailable",
- }
-
- #
- # param error: sort_item
- def test_error_3(self, client, db):
- # request target API
- resp = client.get(
- self.base_url.format(self.test_token_address),
- params={"sort_item": "block_timestamp12345"},
- )
-
- # assertion
- assert resp.status_code == 422
- assumed_response = {
- "meta": {"code": 1, "title": "RequestValidationError"},
- "detail": [
- {
- "ctx": {
- "expected": "'block_timestamp', 'from_address', "
- "'to_address' or 'amount'"
- },
- "input": "block_timestamp12345",
- "loc": ["query", "sort_item"],
- "msg": "Input should be 'block_timestamp', 'from_address', "
- "'to_address' or 'amount'",
- "type": "enum",
- }
- ],
- }
- assert resp.json() == assumed_response
-
- #
- # param error: sort_order(min)
- def test_error_4(self, client, db):
- # request target API
- resp = client.get(
- self.base_url.format(self.test_token_address), params={"sort_order": -1}
- )
-
- # assertion
- assert resp.status_code == 422
- assumed_response = {
- "meta": {"code": 1, "title": "RequestValidationError"},
- "detail": [
- {
- "ctx": {"expected": "0 or 1"},
- "input": -1,
- "loc": ["query", "sort_order"],
- "msg": "Input should be 0 or 1",
- "type": "enum",
- }
- ],
- }
- assert resp.json() == assumed_response
-
- #
- # param error: sort_order(max)
- def test_error_5(self, client, db):
- # request target API
- resp = client.get(
- self.base_url.format(self.test_token_address), params={"sort_order": 2}
- )
-
- # assertion
- assert resp.status_code == 422
- assumed_response = {
- "meta": {"code": 1, "title": "RequestValidationError"},
- "detail": [
- {
- "ctx": {"expected": "0 or 1"},
- "input": 2,
- "loc": ["query", "sort_order"],
- "msg": "Input should be 0 or 1",
- "type": "enum",
- }
- ],
- }
- assert resp.json() == assumed_response
diff --git a/tests/test_app_routers_share_transfers_{token_address}_GET.py b/tests/test_app_routers_share_transfers_{token_address}_GET.py
deleted file mode 100644
index 11ebeaa9..00000000
--- a/tests/test_app_routers_share_transfers_{token_address}_GET.py
+++ /dev/null
@@ -1,1267 +0,0 @@
-"""
-Copyright BOOSTRY Co., Ltd.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-
-You may obtain a copy of the License at
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-
-See the License for the specific language governing permissions and
-limitations under the License.
-
-SPDX-License-Identifier: Apache-2.0
-"""
-
-from datetime import datetime
-
-from pytz import timezone
-
-import config
-from app.model.db import (
- IDXPersonalInfo,
- IDXTransfer,
- IDXTransferSourceEventType,
- Token,
- TokenType,
- TokenVersion,
-)
-
-local_tz = timezone(config.TZ)
-
-
-class TestAppRoutersShareTransfersGET:
- # target API endpoint
- base_url = "/share/transfers/{}"
-
- test_transaction_hash = "test_transaction_hash"
- test_issuer_address = "test_issuer_address"
- test_token_address = "test_token_address"
- test_from_address = "test_from_address"
- test_to_address = "test_to_address"
- test_block_timestamp = [
- datetime.strptime("2022/01/02 15:20:30", "%Y/%m/%d %H:%M:%S"), # JST 2022/01/03
- datetime.strptime("2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"), # JST 2022/01/02
- datetime.strptime("2022/01/02 00:20:30", "%Y/%m/%d %H:%M:%S"), # JST 2022/01/02
- ]
- test_block_timestamp_str = [
- "2022-01-03T00:20:30+09:00",
- "2022-01-02T00:20:30+09:00",
- "2022-01-02T09:20:30+09:00",
- ]
-
- ###########################################################################
- # Normal Case
- ###########################################################################
-
- #
- # default sort
- def test_normal_1(self, client, db):
- # prepare data: Token
- _token = Token()
- _token.type = TokenType.IBET_SHARE.value
- _token.tx_hash = self.test_transaction_hash
- _token.issuer_address = self.test_issuer_address
- _token.token_address = self.test_token_address
- _token.abi = {}
- _token.version = TokenVersion.V_22_12
- db.add(_token)
-
- # prepare data: IDXTransfer
- for i in range(0, 3):
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = self.test_from_address
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = i
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[i]
- db.add(_idx_transfer)
-
- db.commit()
-
- # request target API
- resp = client.get(self.base_url.format(self.test_token_address))
-
- # assertion
- assert resp.status_code == 200
- assumed_response = {
- "result_set": {"count": 3, "offset": None, "limit": None, "total": 3},
- "transfer_history": [
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": None,
- "to_address": self.test_to_address,
- "to_address_personal_information": None,
- "amount": 0,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[0],
- },
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": None,
- "to_address": self.test_to_address,
- "to_address_personal_information": None,
- "amount": 2,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[2],
- },
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": None,
- "to_address": self.test_to_address,
- "to_address_personal_information": None,
- "amount": 1,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[1],
- },
- ],
- }
- assert resp.json() == assumed_response
-
- #
- # offset, limit
- def test_normal_2_1(self, client, db):
- # prepare data: Token
- _token = Token()
- _token.type = TokenType.IBET_SHARE.value
- _token.tx_hash = self.test_transaction_hash
- _token.issuer_address = self.test_issuer_address
- _token.token_address = self.test_token_address
- _token.abi = {}
- _token.version = TokenVersion.V_22_12
- db.add(_token)
-
- # prepare data: IDXPersonalInfo
- _personal_info_from = IDXPersonalInfo()
- _personal_info_from.account_address = self.test_from_address
- _personal_info_from.issuer_address = self.test_issuer_address
- _personal_info_from._personal_info = {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_from)
-
- _personal_info_to = IDXPersonalInfo()
- _personal_info_to.account_address = self.test_to_address
- _personal_info_to.issuer_address = self.test_issuer_address
- _personal_info_to._personal_info = {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- "birth": "birth_test2",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_to)
-
- # prepare data: IDXTransfer
- for i in range(0, 3):
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = self.test_from_address
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = i
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[i]
- db.add(_idx_transfer)
-
- db.commit()
-
- # request target API
- resp = client.get(
- self.base_url.format(self.test_token_address) + "?offset=1&limit=1"
- )
-
- # assertion
- assert resp.status_code == 200
- assumed_response = {
- "result_set": {"count": 3, "offset": 1, "limit": 1, "total": 3},
- "transfer_history": [
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": {
- "address": "address_test1",
- "birth": "birth_test1",
- "email": "email_test1",
- "is_corporate": False,
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "tax_category": 10,
- },
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 2,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[2],
- },
- ],
- }
- assert resp.json() == assumed_response
-
- #
- # filter: source_event
- def test_normal_2_2(self, client, db):
- # prepare data: Token
- _token = Token()
- _token.type = TokenType.IBET_SHARE.value
- _token.tx_hash = self.test_transaction_hash
- _token.issuer_address = self.test_issuer_address
- _token.token_address = self.test_token_address
- _token.abi = {}
- _token.version = TokenVersion.V_22_12
- db.add(_token)
-
- # prepare data: IDXPersonalInfo
- _personal_info_from = IDXPersonalInfo()
- _personal_info_from.account_address = self.test_from_address
- _personal_info_from.issuer_address = self.test_issuer_address
- _personal_info_from._personal_info = {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_from)
-
- _personal_info_to = IDXPersonalInfo()
- _personal_info_to.account_address = self.test_to_address
- _personal_info_to.issuer_address = self.test_issuer_address
- _personal_info_to._personal_info = {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- "birth": "birth_test2",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_to)
-
- # prepare data: IDXTransfer
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = "test_from_address_2"
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 0
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[0]
- db.add(_idx_transfer)
-
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = "test_from_address_2"
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 1
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[1]
- db.add(_idx_transfer)
-
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = "test_from_address_1"
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 2
- _idx_transfer.source_event = IDXTransferSourceEventType.UNLOCK.value
- _idx_transfer.data = {"message": "unlock"}
- _idx_transfer.block_timestamp = self.test_block_timestamp[2]
- db.add(_idx_transfer)
-
- db.commit()
-
- # request target API
- resp = client.get(
- self.base_url.format(self.test_token_address),
- params={"source_event": IDXTransferSourceEventType.UNLOCK.value},
- )
-
- # assertion
- assert resp.status_code == 200
- assumed_response = {
- "result_set": {"count": 1, "offset": None, "limit": None, "total": 3},
- "transfer_history": [
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": "test_from_address_1",
- "from_address_personal_information": None,
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 2,
- "source_event": IDXTransferSourceEventType.UNLOCK.value,
- "data": {"message": "unlock"},
- "block_timestamp": self.test_block_timestamp_str[2],
- },
- ],
- }
- assert resp.json() == assumed_response
-
- #
- # filter: data
- def test_normal_2_3(self, client, db):
- # prepare data: Token
- _token = Token()
- _token.type = TokenType.IBET_SHARE.value
- _token.tx_hash = self.test_transaction_hash
- _token.issuer_address = self.test_issuer_address
- _token.token_address = self.test_token_address
- _token.abi = {}
- _token.version = TokenVersion.V_22_12
- db.add(_token)
-
- # prepare data: IDXPersonalInfo
- _personal_info_from = IDXPersonalInfo()
- _personal_info_from.account_address = self.test_from_address
- _personal_info_from.issuer_address = self.test_issuer_address
- _personal_info_from._personal_info = {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_from)
-
- _personal_info_to = IDXPersonalInfo()
- _personal_info_to.account_address = self.test_to_address
- _personal_info_to.issuer_address = self.test_issuer_address
- _personal_info_to._personal_info = {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- "birth": "birth_test2",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_to)
-
- # prepare data: IDXTransfer
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = "test_from_address_2"
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 0
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[0]
- db.add(_idx_transfer)
-
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = "test_from_address_2"
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 1
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[1]
- db.add(_idx_transfer)
-
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = "test_from_address_1"
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 2
- _idx_transfer.source_event = IDXTransferSourceEventType.UNLOCK.value
- _idx_transfer.data = {"message": "unlock"}
- _idx_transfer.block_timestamp = self.test_block_timestamp[2]
- db.add(_idx_transfer)
-
- db.commit()
-
- # request target API
- resp = client.get(
- self.base_url.format(self.test_token_address), params={"data": "unlo"}
- )
-
- # assertion
- assert resp.status_code == 200
- assumed_response = {
- "result_set": {"count": 1, "offset": None, "limit": None, "total": 3},
- "transfer_history": [
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": "test_from_address_1",
- "from_address_personal_information": None,
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 2,
- "source_event": IDXTransferSourceEventType.UNLOCK.value,
- "data": {"message": "unlock"},
- "block_timestamp": self.test_block_timestamp_str[2],
- }
- ],
- }
- assert resp.json() == assumed_response
-
- #
- # sort: block_timestamp ASC
- def test_normal_3(self, client, db):
- # prepare data: Token
- _token = Token()
- _token.type = TokenType.IBET_SHARE.value
- _token.tx_hash = self.test_transaction_hash
- _token.issuer_address = self.test_issuer_address
- _token.token_address = self.test_token_address
- _token.abi = {}
- _token.version = TokenVersion.V_22_12
- db.add(_token)
-
- # prepare data: IDXPersonalInfo
- _personal_info_from = IDXPersonalInfo()
- _personal_info_from.account_address = self.test_from_address
- _personal_info_from.issuer_address = self.test_issuer_address
- _personal_info_from._personal_info = {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_from)
-
- _personal_info_to = IDXPersonalInfo()
- _personal_info_to.account_address = self.test_to_address
- _personal_info_to.issuer_address = self.test_issuer_address
- _personal_info_to._personal_info = {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- "birth": "birth_test2",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_to)
-
- # prepare data: IDXTransfer
- for i in range(0, 3):
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = self.test_from_address
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = i
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[i]
- db.add(_idx_transfer)
-
- db.commit()
-
- # request target API
- resp = client.get(
- self.base_url.format(self.test_token_address),
- params={
- "sort_item": "block_timestamp",
- "sort_order": 0,
- },
- )
-
- # assertion
- assert resp.status_code == 200
- assumed_response = {
- "result_set": {"count": 3, "offset": None, "limit": None, "total": 3},
- "transfer_history": [
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": {
- "address": "address_test1",
- "birth": "birth_test1",
- "email": "email_test1",
- "is_corporate": False,
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "tax_category": 10,
- },
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 1,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[1],
- },
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": {
- "address": "address_test1",
- "birth": "birth_test1",
- "email": "email_test1",
- "is_corporate": False,
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "tax_category": 10,
- },
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 2,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[2],
- },
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": {
- "address": "address_test1",
- "birth": "birth_test1",
- "email": "email_test1",
- "is_corporate": False,
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "tax_category": 10,
- },
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 0,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[0],
- },
- ],
- }
- assert resp.json() == assumed_response
-
- #
- # sort: from_address ASC
- def test_normal_4(self, client, db):
- # prepare data: Token
- _token = Token()
- _token.type = TokenType.IBET_SHARE.value
- _token.tx_hash = self.test_transaction_hash
- _token.issuer_address = self.test_issuer_address
- _token.token_address = self.test_token_address
- _token.abi = {}
- _token.version = TokenVersion.V_22_12
- db.add(_token)
-
- # prepare data: IDXPersonalInfo
- _personal_info_from = IDXPersonalInfo()
- _personal_info_from.account_address = self.test_from_address
- _personal_info_from.issuer_address = self.test_issuer_address
- _personal_info_from._personal_info = {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_from)
-
- _personal_info_to = IDXPersonalInfo()
- _personal_info_to.account_address = self.test_to_address
- _personal_info_to.issuer_address = self.test_issuer_address
- _personal_info_to._personal_info = {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- "birth": "birth_test2",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_to)
-
- # prepare data: IDXTransfer
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = "test_from_address_2"
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 0
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[0]
- db.add(_idx_transfer)
-
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = "test_from_address_2"
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 1
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[1]
- db.add(_idx_transfer)
-
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = "test_from_address_1"
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 2
- _idx_transfer.source_event = IDXTransferSourceEventType.UNLOCK.value
- _idx_transfer.data = {"message": "unlock"}
- _idx_transfer.block_timestamp = self.test_block_timestamp[2]
- db.add(_idx_transfer)
-
- db.commit()
-
- # request target API
- resp = client.get(
- self.base_url.format(self.test_token_address),
- params={
- "sort_item": "from_address",
- "sort_order": 0,
- },
- )
-
- # assertion
- assert resp.status_code == 200
- assumed_response = {
- "result_set": {"count": 3, "offset": None, "limit": None, "total": 3},
- "transfer_history": [
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": "test_from_address_1",
- "from_address_personal_information": None,
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 2,
- "source_event": IDXTransferSourceEventType.UNLOCK.value,
- "data": {"message": "unlock"},
- "block_timestamp": self.test_block_timestamp_str[2],
- },
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": "test_from_address_2",
- "from_address_personal_information": None,
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 0,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[0],
- },
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": "test_from_address_2",
- "from_address_personal_information": None,
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 1,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[1],
- },
- ],
- }
- assert resp.json() == assumed_response
-
- #
- # sort: to_address DESC
- def test_normal_5(self, client, db):
- # prepare data: Token
- _token = Token()
- _token.type = TokenType.IBET_SHARE.value
- _token.tx_hash = self.test_transaction_hash
- _token.issuer_address = self.test_issuer_address
- _token.token_address = self.test_token_address
- _token.abi = {}
- _token.version = TokenVersion.V_22_12
- db.add(_token)
-
- # prepare data: IDXPersonalInfo
- _personal_info_from = IDXPersonalInfo()
- _personal_info_from.account_address = self.test_from_address
- _personal_info_from.issuer_address = self.test_issuer_address
- _personal_info_from._personal_info = {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_from)
-
- _personal_info_to = IDXPersonalInfo()
- _personal_info_to.account_address = self.test_to_address
- _personal_info_to.issuer_address = self.test_issuer_address
- _personal_info_to._personal_info = {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- "birth": "birth_test2",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_to)
-
- # prepare data: IDXTransfer
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = self.test_from_address
- _idx_transfer.to_address = "test_to_address_2"
- _idx_transfer.amount = 0
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[0]
- db.add(_idx_transfer)
-
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = self.test_from_address
- _idx_transfer.to_address = "test_to_address_1"
- _idx_transfer.amount = 1
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[1]
- db.add(_idx_transfer)
-
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = self.test_from_address
- _idx_transfer.to_address = "test_to_address_1"
- _idx_transfer.amount = 2
- _idx_transfer.source_event = IDXTransferSourceEventType.UNLOCK.value
- _idx_transfer.data = {"message": "unlock"}
- _idx_transfer.block_timestamp = self.test_block_timestamp[2]
- db.add(_idx_transfer)
-
- db.commit()
-
- # request target API
- resp = client.get(
- self.base_url.format(self.test_token_address),
- params={
- "sort_item": "to_address",
- "sort_order": 1,
- },
- )
-
- # assertion
- assert resp.status_code == 200
- assumed_response = {
- "result_set": {"count": 3, "offset": None, "limit": None, "total": 3},
- "transfer_history": [
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": {
- "address": "address_test1",
- "birth": "birth_test1",
- "email": "email_test1",
- "is_corporate": False,
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "tax_category": 10,
- },
- "to_address": "test_to_address_2",
- "to_address_personal_information": None,
- "amount": 0,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[0],
- },
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": {
- "address": "address_test1",
- "birth": "birth_test1",
- "email": "email_test1",
- "is_corporate": False,
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "tax_category": 10,
- },
- "to_address": "test_to_address_1",
- "to_address_personal_information": None,
- "amount": 2,
- "source_event": IDXTransferSourceEventType.UNLOCK.value,
- "data": {"message": "unlock"},
- "block_timestamp": self.test_block_timestamp_str[2],
- },
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": {
- "address": "address_test1",
- "birth": "birth_test1",
- "email": "email_test1",
- "is_corporate": False,
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "tax_category": 10,
- },
- "to_address": "test_to_address_1",
- "to_address_personal_information": None,
- "amount": 1,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[1],
- },
- ],
- }
- assert resp.json() == assumed_response
-
- #
- # sort: amount DESC
- def test_normal_6(self, client, db):
- # prepare data: Token
- _token = Token()
- _token.type = TokenType.IBET_SHARE.value
- _token.tx_hash = self.test_transaction_hash
- _token.issuer_address = self.test_issuer_address
- _token.token_address = self.test_token_address
- _token.abi = {}
- _token.version = TokenVersion.V_22_12
- db.add(_token)
-
- # prepare data: IDXPersonalInfo
- _personal_info_from = IDXPersonalInfo()
- _personal_info_from.account_address = self.test_from_address
- _personal_info_from.issuer_address = self.test_issuer_address
- _personal_info_from._personal_info = {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_from)
-
- _personal_info_to = IDXPersonalInfo()
- _personal_info_to.account_address = self.test_to_address
- _personal_info_to.issuer_address = self.test_issuer_address
- _personal_info_to._personal_info = {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- "birth": "birth_test2",
- "is_corporate": False,
- "tax_category": 10,
- } # latest data
- db.add(_personal_info_to)
-
- # prepare data: IDXTransfer
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = self.test_from_address
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 1
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[0]
- db.add(_idx_transfer)
-
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = self.test_from_address
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 2
- _idx_transfer.source_event = IDXTransferSourceEventType.TRANSFER.value
- _idx_transfer.data = None
- _idx_transfer.block_timestamp = self.test_block_timestamp[1]
- db.add(_idx_transfer)
-
- _idx_transfer = IDXTransfer()
- _idx_transfer.transaction_hash = self.test_transaction_hash
- _idx_transfer.token_address = self.test_token_address
- _idx_transfer.from_address = self.test_from_address
- _idx_transfer.to_address = self.test_to_address
- _idx_transfer.amount = 2
- _idx_transfer.source_event = IDXTransferSourceEventType.UNLOCK.value
- _idx_transfer.data = {"message": "unlock"}
- _idx_transfer.block_timestamp = self.test_block_timestamp[2]
- db.add(_idx_transfer)
-
- db.commit()
-
- # request target API
- resp = client.get(
- self.base_url.format(self.test_token_address),
- params={
- "sort_item": "amount",
- "sort_order": 0,
- },
- )
-
- # assertion
- assert resp.status_code == 200
- assumed_response = {
- "result_set": {"count": 3, "offset": None, "limit": None, "total": 3},
- "transfer_history": [
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": {
- "address": "address_test1",
- "birth": "birth_test1",
- "email": "email_test1",
- "is_corporate": False,
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "tax_category": 10,
- },
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 1,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[0],
- },
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": {
- "address": "address_test1",
- "birth": "birth_test1",
- "email": "email_test1",
- "is_corporate": False,
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "tax_category": 10,
- },
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 2,
- "source_event": IDXTransferSourceEventType.UNLOCK.value,
- "data": {"message": "unlock"},
- "block_timestamp": self.test_block_timestamp_str[2],
- },
- {
- "transaction_hash": self.test_transaction_hash,
- "token_address": self.test_token_address,
- "from_address": self.test_from_address,
- "from_address_personal_information": {
- "address": "address_test1",
- "birth": "birth_test1",
- "email": "email_test1",
- "is_corporate": False,
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "tax_category": 10,
- },
- "to_address": self.test_to_address,
- "to_address_personal_information": {
- "address": "address_test2",
- "birth": "birth_test2",
- "email": "email_test2",
- "is_corporate": False,
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "tax_category": 10,
- },
- "amount": 2,
- "source_event": IDXTransferSourceEventType.TRANSFER.value,
- "data": None,
- "block_timestamp": self.test_block_timestamp_str[1],
- },
- ],
- }
- assert resp.json() == assumed_response
-
- ###########################################################################
- # Error Case
- ###########################################################################
-
- #
- # token not found
- def test_error_1(self, client, db):
- # request target API
- resp = client.get(self.base_url.format(self.test_token_address))
-
- # assertion
- assert resp.status_code == 404
- assumed_response = {
- "meta": {"code": 1, "title": "NotFound"},
- "detail": "token not found",
- }
- assert resp.json() == assumed_response
-
- #
- # processing token
- def test_error_2(self, client, db):
- # prepare data: Token
- _token = Token()
- _token.type = TokenType.IBET_SHARE.value
- _token.tx_hash = self.test_transaction_hash
- _token.issuer_address = self.test_issuer_address
- _token.token_address = self.test_token_address
- _token.abi = {}
- _token.token_status = 0
- _token.version = TokenVersion.V_22_12
- db.add(_token)
-
- db.commit()
-
- # request target API
- resp = client.get(self.base_url.format(self.test_token_address))
-
- # assertion
- assert resp.status_code == 400
- assert resp.json() == {
- "meta": {"code": 1, "title": "InvalidParameterError"},
- "detail": "this token is temporarily unavailable",
- }
-
- #
- # param error: sort_item
- def test_error_3(self, client, db):
- # request target API
- resp = client.get(
- self.base_url.format(self.test_token_address),
- params={"sort_item": "block_timestamp12345"},
- )
-
- # assertion
- assert resp.status_code == 422
- assumed_response = {
- "meta": {"code": 1, "title": "RequestValidationError"},
- "detail": [
- {
- "ctx": {
- "expected": "'block_timestamp', 'from_address', "
- "'to_address' or 'amount'"
- },
- "input": "block_timestamp12345",
- "loc": ["query", "sort_item"],
- "msg": "Input should be 'block_timestamp', 'from_address', "
- "'to_address' or 'amount'",
- "type": "enum",
- }
- ],
- }
- assert resp.json() == assumed_response
-
- #
- # param error: sort_order(min)
- def test_error_4(self, client, db):
- # request target API
- resp = client.get(
- self.base_url.format(self.test_token_address), params={"sort_order": -1}
- )
-
- # assertion
- assert resp.status_code == 422
- assumed_response = {
- "meta": {"code": 1, "title": "RequestValidationError"},
- "detail": [
- {
- "ctx": {"expected": "0 or 1"},
- "input": -1,
- "loc": ["query", "sort_order"],
- "msg": "Input should be 0 or 1",
- "type": "enum",
- }
- ],
- }
- assert resp.json() == assumed_response
-
- #
- # param error: sort_order(max)
- def test_error_5(self, client, db):
- # request target API
- resp = client.get(
- self.base_url.format(self.test_token_address), params={"sort_order": 2}
- )
-
- # assertion
- assert resp.status_code == 422
- assumed_response = {
- "meta": {"code": 1, "title": "RequestValidationError"},
- "detail": [
- {
- "ctx": {"expected": "0 or 1"},
- "input": 2,
- "loc": ["query", "sort_order"],
- "msg": "Input should be 0 or 1",
- "type": "enum",
- }
- ],
- }
- assert resp.json() == assumed_response
diff --git a/tests/test_app_routers_token_holders_personal_info_GET.py b/tests/test_app_routers_token_holders_personal_info_GET.py
deleted file mode 100644
index fc15a487..00000000
--- a/tests/test_app_routers_token_holders_personal_info_GET.py
+++ /dev/null
@@ -1,450 +0,0 @@
-"""
-Copyright BOOSTRY Co., Ltd.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-
-You may obtain a copy of the License at
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-
-See the License for the specific language governing permissions and
-limitations under the License.
-
-SPDX-License-Identifier: Apache-2.0
-"""
-
-from unittest import mock
-
-from app.model.db import IDXPersonalInfo
-from tests.account_config import config_eth_account
-
-
-class TestAppRoutersTokenHoldersPersonalInfoGET:
- # target API endpoint
- url = "/token/holders/personal_info"
-
- ###########################################################################
- # Normal Case
- ###########################################################################
-
- #
- # 0 record
- def test_normal_1(self, client, db):
- issuer_account = config_eth_account("user1")
- issuer_address = issuer_account["address"]
-
- # request target API
- resp = client.get(
- self.url,
- headers={
- "issuer-address": issuer_address,
- },
- )
-
- assert resp.status_code == 200
- assert resp.json() == {
- "result_set": {"count": 0, "limit": None, "offset": None, "total": 0},
- "personal_info": [],
- }
-
- #
- # 1 record
- def test_normal_2(self, client, db):
- issuer_account = config_eth_account("user1")
- issuer_address = issuer_account["address"]
- account_address1 = "account_address1"
-
- # prepare data
- personal_info_idx = IDXPersonalInfo()
- personal_info_idx.issuer_address = issuer_address
- personal_info_idx.account_address = account_address1
- personal_info_idx.personal_info = {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- }
- db.add(personal_info_idx)
-
- db.commit()
-
- # request target API
- resp = client.get(
- self.url,
- headers={
- "issuer-address": issuer_address,
- },
- )
-
- assert resp.status_code == 200
- assert resp.json() == {
- "result_set": {"count": 1, "limit": None, "offset": None, "total": 1},
- "personal_info": [
- {
- "id": 1,
- "account_address": account_address1,
- "personal_info": {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- },
- "created": mock.ANY,
- }
- ],
- }
-
- #
- # Multi record
- def test_normal_3(self, client, db):
- issuer_account = config_eth_account("user1")
- issuer_address = issuer_account["address"]
- account_address1 = "account_address1"
- account_address2 = "account_address2"
- account_address3 = "account_address3"
-
- # prepare data
- personal_info_idx = IDXPersonalInfo()
- personal_info_idx.issuer_address = issuer_address
- personal_info_idx.account_address = account_address1
- personal_info_idx.personal_info = {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- }
- db.add(personal_info_idx)
-
- personal_info_idx = IDXPersonalInfo()
- personal_info_idx.issuer_address = issuer_address
- personal_info_idx.account_address = account_address2
- personal_info_idx.personal_info = {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- # "birth": None,
- "is_corporate": False,
- "tax_category": 10,
- }
- db.add(personal_info_idx)
-
- personal_info_idx = IDXPersonalInfo()
- personal_info_idx.issuer_address = issuer_address
- personal_info_idx.account_address = account_address3
- personal_info_idx.personal_info = {
- "key_manager": "key_manager_test3",
- "name": "name_test3",
- "postal_code": "postal_code_test3",
- "address": "address_test3",
- "email": "email_test3",
- "birth": None,
- "is_corporate": False,
- "tax_category": 10,
- }
- db.add(personal_info_idx)
-
- db.commit()
-
- # request target API
- resp = client.get(
- self.url,
- headers={
- "issuer-address": issuer_address,
- },
- )
-
- assert resp.status_code == 200
- assert resp.json() == {
- "result_set": {"count": 3, "limit": None, "offset": None, "total": 3},
- "personal_info": [
- {
- "id": 1,
- "account_address": account_address1,
- "personal_info": {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- },
- "created": mock.ANY,
- },
- {
- "id": 2,
- "account_address": account_address2,
- "personal_info": {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- "birth": None,
- "is_corporate": False,
- "tax_category": 10,
- },
- "created": mock.ANY,
- },
- {
- "id": 3,
- "account_address": account_address3,
- "personal_info": {
- "key_manager": "key_manager_test3",
- "name": "name_test3",
- "postal_code": "postal_code_test3",
- "address": "address_test3",
- "email": "email_test3",
- "birth": None,
- "is_corporate": False,
- "tax_category": 10,
- },
- "created": mock.ANY,
- },
- ],
- }
-
- #
- # Pagination
- def test_normal_4(self, client, db):
- issuer_account = config_eth_account("user1")
- issuer_address = issuer_account["address"]
- account_address1 = "account_address1"
- account_address2 = "account_address2"
- account_address3 = "account_address3"
-
- # prepare data
- personal_info_idx = IDXPersonalInfo()
- personal_info_idx.issuer_address = issuer_address
- personal_info_idx.account_address = account_address1
- personal_info_idx.personal_info = {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- }
- db.add(personal_info_idx)
-
- personal_info_idx = IDXPersonalInfo()
- personal_info_idx.issuer_address = issuer_address
- personal_info_idx.account_address = account_address2
- personal_info_idx.personal_info = {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- # "birth": None,
- "is_corporate": False,
- "tax_category": 10,
- }
- db.add(personal_info_idx)
-
- personal_info_idx = IDXPersonalInfo()
- personal_info_idx.issuer_address = issuer_address
- personal_info_idx.account_address = account_address3
- personal_info_idx.personal_info = {
- "key_manager": "key_manager_test3",
- "name": "name_test3",
- "postal_code": "postal_code_test3",
- "address": "address_test3",
- "email": "email_test3",
- "birth": None,
- "is_corporate": False,
- "tax_category": 10,
- }
- db.add(personal_info_idx)
-
- db.commit()
-
- # request target API
- req_param = {"limit": 2, "offset": 1}
- resp = client.get(
- self.url,
- params=req_param,
- headers={
- "issuer-address": issuer_address,
- },
- )
-
- assert resp.status_code == 200
- assert resp.json() == {
- "result_set": {"count": 3, "limit": 2, "offset": 1, "total": 3},
- "personal_info": [
- {
- "id": 2,
- "account_address": account_address2,
- "personal_info": {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- "birth": None,
- "is_corporate": False,
- "tax_category": 10,
- },
- "created": mock.ANY,
- },
- {
- "id": 3,
- "account_address": account_address3,
- "personal_info": {
- "key_manager": "key_manager_test3",
- "name": "name_test3",
- "postal_code": "postal_code_test3",
- "address": "address_test3",
- "email": "email_test3",
- "birth": None,
- "is_corporate": False,
- "tax_category": 10,
- },
- "created": mock.ANY,
- },
- ],
- }
-
- #
- # Sort
- def test_normal_5(self, client, db):
- issuer_account = config_eth_account("user1")
- issuer_address = issuer_account["address"]
- account_address1 = "account_address1"
- account_address2 = "account_address2"
- account_address3 = "account_address3"
-
- # prepare data
- personal_info_idx = IDXPersonalInfo()
- personal_info_idx.issuer_address = issuer_address
- personal_info_idx.account_address = account_address1
- personal_info_idx.personal_info = {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- }
- personal_info_idx.created = "2023-10-23 00:00:00"
- db.add(personal_info_idx)
-
- personal_info_idx = IDXPersonalInfo()
- personal_info_idx.issuer_address = issuer_address
- personal_info_idx.account_address = account_address2
- personal_info_idx.personal_info = {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- # "birth": None,
- "is_corporate": False,
- "tax_category": 10,
- }
- personal_info_idx.created = "2023-10-23 00:00:01"
- db.add(personal_info_idx)
-
- personal_info_idx = IDXPersonalInfo()
- personal_info_idx.issuer_address = issuer_address
- personal_info_idx.account_address = account_address3
- personal_info_idx.personal_info = {
- "key_manager": "key_manager_test3",
- "name": "name_test3",
- "postal_code": "postal_code_test3",
- "address": "address_test3",
- "email": "email_test3",
- "birth": None,
- "is_corporate": False,
- "tax_category": 10,
- }
- personal_info_idx.created = "2023-10-23 00:00:02"
- db.add(personal_info_idx)
-
- db.commit()
-
- # request target API
- req_param = {"sort_order": 1}
- resp = client.get(
- self.url,
- params=req_param,
- headers={
- "issuer-address": issuer_address,
- },
- )
-
- assert resp.status_code == 200
- assert resp.json() == {
- "result_set": {"count": 3, "limit": None, "offset": None, "total": 3},
- "personal_info": [
- {
- "id": 3,
- "account_address": account_address3,
- "personal_info": {
- "key_manager": "key_manager_test3",
- "name": "name_test3",
- "postal_code": "postal_code_test3",
- "address": "address_test3",
- "email": "email_test3",
- "birth": None,
- "is_corporate": False,
- "tax_category": 10,
- },
- "created": mock.ANY,
- },
- {
- "id": 2,
- "account_address": account_address2,
- "personal_info": {
- "key_manager": "key_manager_test2",
- "name": "name_test2",
- "postal_code": "postal_code_test2",
- "address": "address_test2",
- "email": "email_test2",
- "birth": None,
- "is_corporate": False,
- "tax_category": 10,
- },
- "created": mock.ANY,
- },
- {
- "id": 1,
- "account_address": account_address1,
- "personal_info": {
- "key_manager": "key_manager_test1",
- "name": "name_test1",
- "postal_code": "postal_code_test1",
- "address": "address_test1",
- "email": "email_test1",
- "birth": "birth_test1",
- "is_corporate": False,
- "tax_category": 10,
- },
- "created": mock.ANY,
- },
- ],
- }
diff --git a/tests/test_utils_ledger_utils.py b/tests/test_utils_ledger_utils.py
deleted file mode 100644
index 1e45cea2..00000000
--- a/tests/test_utils_ledger_utils.py
+++ /dev/null
@@ -1,1178 +0,0 @@
-"""
-Copyright BOOSTRY Co., Ltd.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-
-You may obtain a copy of the License at
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-
-See the License for the specific language governing permissions and
-limitations under the License.
-
-SPDX-License-Identifier: Apache-2.0
-"""
-
-from datetime import datetime
-
-import pytest
-import pytz
-from eth_keyfile import decode_keyfile_json
-from sqlalchemy import select
-from web3 import Web3
-from web3.middleware import geth_poa_middleware
-
-from app.model.blockchain import (
- IbetShareContract,
- IbetStraightBondContract,
- PersonalInfoContract,
-)
-from app.model.blockchain.tx_params.ibet_share import (
- UpdateParams as IbetShareUpdateParams,
-)
-from app.model.blockchain.tx_params.ibet_straight_bond import (
- UpdateParams as IbetStraightBondUpdateParams,
-)
-from app.model.db import (
- UTXO,
- Account,
- AccountRsaStatus,
- IDXPersonalInfo,
- Ledger,
- LedgerDetailsData,
- LedgerDetailsDataType,
- LedgerDetailsTemplate,
- LedgerTemplate,
- Notification,
- NotificationType,
- Token,
- TokenType,
- TokenVersion,
-)
-from app.utils import ledger_utils
-from app.utils.contract_utils import ContractUtils
-from app.utils.e2ee_utils import E2EEUtils
-from config import CHAIN_ID, TX_GAS_LIMIT, TZ, WEB3_HTTP_PROVIDER, ZERO_ADDRESS
-from tests.account_config import config_eth_account
-
-web3 = Web3(Web3.HTTPProvider(WEB3_HTTP_PROVIDER))
-web3.middleware_onion.inject(geth_poa_middleware, layer=0)
-
-
-async def deploy_bond_token_contract(
- address, private_key, personal_info_contract_address
-):
- arguments = [
- "token.name",
- "token.symbol",
- 100,
- 20,
- "JPY",
- "token.redemption_date",
- 30,
- "JPY",
- "token.return_date",
- "token.return_amount",
- "token.purpose",
- ]
- bond_contrat = IbetStraightBondContract()
- contract_address, _, _ = await bond_contrat.create(arguments, address, private_key)
-
- data = IbetStraightBondUpdateParams()
- data.personal_info_contract_address = personal_info_contract_address
- data.face_value_currency = "JPY"
- await bond_contrat.update(data, address, private_key)
-
- return contract_address
-
-
-async def deploy_share_token_contract(
- address, private_key, personal_info_contract_address
-):
- arguments = [
- "token.name",
- "token.symbol",
- 100,
- 20,
- 3,
- "token.dividend_record_date",
- "token.dividend_payment_date",
- "token.cancellation_date",
- 200,
- ]
- share_contract = IbetShareContract()
- contract_address, _, _ = await share_contract.create(
- arguments, address, private_key
- )
-
- data = IbetShareUpdateParams()
- data.personal_info_contract_address = personal_info_contract_address
- await share_contract.update(data, address, private_key)
-
- return contract_address
-
-
-def deploy_personal_info_contract(address, private_key):
- contract_address, _, _ = ContractUtils.deploy_contract(
- "PersonalInfo", [], address, private_key
- )
- return contract_address
-
-
-async def set_personal_info_contract(
- db, contract_address, issuer_account: Account, sender_list
-):
- contract = ContractUtils.get_contract("PersonalInfo", contract_address)
-
- for sender in sender_list:
- tx = contract.functions.register(
- issuer_account.issuer_address, ""
- ).build_transaction(
- {
- "nonce": web3.eth.get_transaction_count(sender["address"]),
- "chainId": CHAIN_ID,
- "from": sender["address"],
- "gas": TX_GAS_LIMIT,
- "gasPrice": 0,
- }
- )
- ContractUtils.send_transaction(tx, sender["private_key"])
-
- personal_info = PersonalInfoContract(issuer_account, contract_address)
- await personal_info.modify_info(sender["address"], sender["data"])
-
-
-class TestCreateLedger:
- ###########################################################################
- # Normal Case
- ###########################################################################
-
- #
- # Share Token
- @pytest.mark.asyncio
- async def test_normal_1(self, db, async_db):
- issuer = config_eth_account("user5")
- issuer_address = issuer["address"]
- issuer_private_key = decode_keyfile_json(
- raw_keyfile_json=issuer["keyfile_json"], password="password".encode("utf-8")
- )
- user_1 = config_eth_account("user1")
- user_address_1 = user_1["address"]
- user_private_key_1 = decode_keyfile_json(
- raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
- )
- user_2 = config_eth_account("user2")
- user_address_2 = user_2["address"]
- user_private_key_2 = decode_keyfile_json(
- raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
- )
-
- # prepare data
- # Account
- _account = Account()
- _account.issuer_address = issuer_address
- _account.keyfile = issuer["keyfile_json"]
- _account.eoa_password = E2EEUtils.encrypt("password")
- _account.rsa_private_key = issuer["rsa_private_key"]
- _account.rsa_public_key = issuer["rsa_public_key"]
- _account.rsa_passphrase = E2EEUtils.encrypt("password")
- _account.rsa_status = AccountRsaStatus.SET.value
- db.add(_account)
-
- # Token
- personal_info_contract_address = deploy_personal_info_contract(
- issuer_address, issuer_private_key
- )
- await set_personal_info_contract(
- db,
- personal_info_contract_address,
- _account,
- [
- {
- "address": user_address_1,
- "private_key": user_private_key_1,
- "data": {
- "name": "name_test_con_1",
- "address": "address_test_con_1",
- },
- },
- {
- "address": user_address_2,
- "private_key": user_private_key_2,
- "data": {
- "name": "name_test_con_2",
- "address": "address_test_con_2",
- },
- },
- ],
- )
- token_address_1 = await deploy_share_token_contract(
- issuer_address, issuer_private_key, personal_info_contract_address
- )
- _token_1 = Token()
- _token_1.type = TokenType.IBET_SHARE.value
- _token_1.tx_hash = ""
- _token_1.issuer_address = issuer_address
- _token_1.token_address = token_address_1
- _token_1.abi = {}
- _token_1.version = TokenVersion.V_22_12
- db.add(_token_1)
-
- # IDXPersonalInfo(only user_1)
- _idx_personal_info_1 = IDXPersonalInfo()
- _idx_personal_info_1.account_address = user_address_1
- _idx_personal_info_1.issuer_address = issuer_address
- _idx_personal_info_1.personal_info = {
- "name": "name_test_db_1",
- "address": "address_test_db_1",
- }
- db.add(_idx_personal_info_1)
-
- # UTXO
- # user_1: "2022/01/01" = 100 + 10, "2022/01/02" = 30 + 40
- # user_2: "2022/01/01" = 200 + 20, "2022/01/02" = 40 + 2
- _utxo_1 = UTXO()
- _utxo_1.transaction_hash = "tx1"
- _utxo_1.account_address = user_address_1
- _utxo_1.token_address = token_address_1
- _utxo_1.amount = 100
- _utxo_1.block_number = 1
- _utxo_1.block_timestamp = datetime.strptime(
- "2021/12/31 15:20:30", "%Y/%m/%d %H:%M:%S"
- ) # JST 2022/01/01
- db.add(_utxo_1)
-
- _utxo_2 = UTXO()
- _utxo_2.transaction_hash = "tx2"
- _utxo_2.account_address = user_address_1
- _utxo_2.token_address = token_address_1
- _utxo_2.amount = 10
- _utxo_2.block_number = 2
- _utxo_2.block_timestamp = datetime.strptime(
- "2022/01/01 01:20:30", "%Y/%m/%d %H:%M:%S"
- ) # JST 2022/01/01
- db.add(_utxo_2)
-
- _utxo_3 = UTXO()
- _utxo_3.transaction_hash = "tx3"
- _utxo_3.account_address = user_address_1
- _utxo_3.token_address = token_address_1
- _utxo_3.amount = 30
- _utxo_3.block_number = 3
- _utxo_3.block_timestamp = datetime.strptime(
- "2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"
- ) # JST 2022/01/02
- db.add(_utxo_3)
-
- _utxo_4 = UTXO()
- _utxo_4.transaction_hash = "tx4"
- _utxo_4.account_address = user_address_1
- _utxo_4.token_address = token_address_1
- _utxo_4.amount = 40
- _utxo_4.block_number = 4
- _utxo_4.block_timestamp = datetime.strptime(
- "2022/01/02 01:20:30", "%Y/%m/%d %H:%M:%S"
- ) # JST 2022/01/02
- db.add(_utxo_4)
-
- _utxo_5 = UTXO()
- _utxo_5.transaction_hash = "tx5"
- _utxo_5.account_address = user_address_2
- _utxo_5.token_address = token_address_1
- _utxo_5.amount = 200
- _utxo_5.block_number = 5
- _utxo_5.block_timestamp = datetime.strptime(
- "2021/12/31 15:20:30", "%Y/%m/%d %H:%M:%S"
- ) # JST 2022/01/01
- db.add(_utxo_5)
-
- _utxo_6 = UTXO()
- _utxo_6.transaction_hash = "tx6"
- _utxo_6.account_address = user_address_2
- _utxo_6.token_address = token_address_1
- _utxo_6.amount = 20
- _utxo_6.block_number = 6
- _utxo_6.block_timestamp = datetime.strptime(
- "2022/01/01 01:20:30", "%Y/%m/%d %H:%M:%S"
- ) # JST 2022/01/01
- db.add(_utxo_6)
-
- _utxo_7 = UTXO()
- _utxo_7.transaction_hash = "tx7"
- _utxo_7.account_address = user_address_2
- _utxo_7.token_address = token_address_1
- _utxo_7.amount = 40
- _utxo_7.block_number = 7
- _utxo_7.block_timestamp = datetime.strptime(
- "2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"
- ) # JST 2022/01/02
- db.add(_utxo_7)
-
- _utxo_8 = UTXO()
- _utxo_8.transaction_hash = "tx8"
- _utxo_8.account_address = user_address_2
- _utxo_8.token_address = token_address_1
- _utxo_8.amount = 2
- _utxo_8.block_number = 8
- _utxo_8.block_timestamp = datetime.strptime(
- "2022/01/02 01:20:30", "%Y/%m/%d %H:%M:%S"
- ) # JST 2022/01/02
- db.add(_utxo_8)
-
- # Template
- _template = LedgerTemplate()
- _template.token_address = token_address_1
- _template.issuer_address = issuer_address
- _template.headers = [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "テスト項目1": "テスト値1",
- "テスト項目2": {
- "テスト項目A": "テスト値2A",
- "テスト項目B": "テスト値2B",
- },
- "テスト項目3": {
- "テスト項目A": {"テスト項目a": "テスト値3Aa"},
- "テスト項目B": "テスト値3B",
- },
- },
- ]
- _template.token_name = "受益権テスト"
- _template.footers = [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "f-テスト項目1": "f-テスト値1",
- "f-テスト項目2": {
- "f-テスト項目A": "f-テスト値2A",
- "f-テスト項目B": "f-テスト値2B",
- },
- "f-テスト項目3": {
- "f-テスト項目A": {"f-テスト項目a": "f-テスト値3Aa"},
- "f-テスト項目B": "f-テスト値3B",
- },
- },
- ]
- db.add(_template)
-
- # Template Details 1
- _details_1 = LedgerDetailsTemplate()
- _details_1.token_address = token_address_1
- _details_1.token_detail_type = "優先受益権"
- _details_1.headers = [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "test項目1": "test値1",
- "test項目2": {
- "test項目A": "test値2A",
- },
- },
- ]
- _details_1.footers = [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "test-item1": "test-value1",
- "test-item2": {"test-itemA": {"test-itema": "test-value2Aa"}},
- },
- ]
- _details_1.data_type = LedgerDetailsDataType.IBET_FIN.value
- _details_1.data_source = token_address_1
- db.add(_details_1)
-
- # Template Details 2
- _details_2 = LedgerDetailsTemplate()
- _details_2.token_address = token_address_1
- _details_2.token_detail_type = "劣後受益権"
- _details_2.headers = [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "d-test項目1": "d-test値1",
- "d-test項目2": "d-test値2",
- },
- ]
- _details_2.footers = [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "f-d-test項目1": "d-test値1",
- "f-d-test項目2": "d-test値2",
- },
- ]
- _details_2.data_type = LedgerDetailsDataType.DB.value
- _details_2.data_source = "data_id_2"
- db.add(_details_2)
-
- # Details 2 Data
- _details_2_data_1 = LedgerDetailsData()
- _details_2_data_1.token_address = token_address_1
- _details_2_data_1.data_id = "data_id_2"
- _details_2_data_1.name = "test_data_name_1"
- _details_2_data_1.address = "test_data_address_1"
- _details_2_data_1.amount = 100
- _details_2_data_1.price = 200
- _details_2_data_1.balance = 20000
- _details_2_data_1.acquisition_date = "2022/03/03"
- db.add(_details_2_data_1)
-
- _details_2_data_2 = LedgerDetailsData()
- _details_2_data_2.token_address = token_address_1
- _details_2_data_2.data_id = "data_id_2"
- _details_2_data_2.name = "test_data_name_2"
- _details_2_data_2.address = "test_data_address_2"
- _details_2_data_2.amount = 30
- _details_2_data_2.price = 40
- _details_2_data_2.balance = 1200
- _details_2_data_2.acquisition_date = "2022/12/03"
- db.add(_details_2_data_2)
-
- db.commit()
-
- # Execute
- await ledger_utils.create_ledger(token_address_1, async_db)
- await async_db.commit()
- await async_db.close()
-
- # assertion
- _notifications = db.scalars(select(Notification)).all()
- assert len(_notifications) == 1
- _notification = db.scalars(select(Notification).limit(1)).first()
- assert _notification.id == 1
- assert _notification.notice_id is not None
- assert _notification.issuer_address == issuer_address
- assert _notification.priority == 0
- assert _notification.type == NotificationType.CREATE_LEDGER_INFO
- assert _notification.code == 0
- assert _notification.metainfo == {
- "token_address": token_address_1,
- "token_type": TokenType.IBET_SHARE.value,
- "ledger_id": 1,
- }
-
- _ledger = db.scalars(select(Ledger).limit(1)).first()
- assert _ledger.id == 1
- assert _ledger.token_address == token_address_1
- assert _ledger.token_type == TokenType.IBET_SHARE.value
- now_ymd = datetime.now(pytz.timezone(TZ)).strftime("%Y/%m/%d")
- assert _ledger.ledger == {
- "created": now_ymd,
- "token_name": "受益権テスト",
- "currency": "",
- "headers": [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "テスト項目1": "テスト値1",
- "テスト項目2": {
- "テスト項目A": "テスト値2A",
- "テスト項目B": "テスト値2B",
- },
- "テスト項目3": {
- "テスト項目A": {"テスト項目a": "テスト値3Aa"},
- "テスト項目B": "テスト値3B",
- },
- },
- ],
- "details": [
- {
- "token_detail_type": "優先受益権",
- "headers": [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "test項目1": "test値1",
- "test項目2": {
- "test項目A": "test値2A",
- },
- },
- ],
- "data": [
- {
- "account_address": user_address_2,
- "name": "name_test_con_2",
- "address": "address_test_con_2",
- "amount": 220,
- "price": 200,
- "balance": 220 * 200,
- "acquisition_date": "2022/01/01",
- },
- {
- "account_address": user_address_2,
- "name": "name_test_con_2",
- "address": "address_test_con_2",
- "amount": 42,
- "price": 200,
- "balance": 42 * 200,
- "acquisition_date": "2022/01/02",
- },
- {
- "account_address": user_address_1,
- "name": "name_test_db_1",
- "address": "address_test_db_1",
- "amount": 110,
- "price": 200,
- "balance": 110 * 200,
- "acquisition_date": "2022/01/01",
- },
- {
- "account_address": user_address_1,
- "name": "name_test_db_1",
- "address": "address_test_db_1",
- "amount": 70,
- "price": 200,
- "balance": 70 * 200,
- "acquisition_date": "2022/01/02",
- },
- ],
- "footers": [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "test-item1": "test-value1",
- "test-item2": {
- "test-itemA": {"test-itema": "test-value2Aa"}
- },
- },
- ],
- },
- {
- "token_detail_type": "劣後受益権",
- "headers": [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "d-test項目1": "d-test値1",
- "d-test項目2": "d-test値2",
- },
- ],
- "data": [
- {
- "account_address": None,
- "name": "test_data_name_1",
- "address": "test_data_address_1",
- "amount": 100,
- "price": 200,
- "balance": 20000,
- "acquisition_date": "2022/03/03",
- },
- {
- "account_address": None,
- "name": "test_data_name_2",
- "address": "test_data_address_2",
- "amount": 30,
- "price": 40,
- "balance": 1200,
- "acquisition_date": "2022/12/03",
- },
- ],
- "footers": [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "f-d-test項目1": "d-test値1",
- "f-d-test項目2": "d-test値2",
- },
- ],
- },
- ],
- "footers": [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "f-テスト項目1": "f-テスト値1",
- "f-テスト項目2": {
- "f-テスト項目A": "f-テスト値2A",
- "f-テスト項目B": "f-テスト値2B",
- },
- "f-テスト項目3": {
- "f-テスト項目A": {"f-テスト項目a": "f-テスト値3Aa"},
- "f-テスト項目B": "f-テスト値3B",
- },
- },
- ],
- }
- db.close()
-
- #
- # Bond Token
- @pytest.mark.asyncio
- async def test_normal_2(self, db, async_db):
- issuer = config_eth_account("user5")
- issuer_address = issuer["address"]
- issuer_private_key = decode_keyfile_json(
- raw_keyfile_json=issuer["keyfile_json"], password="password".encode("utf-8")
- )
- user_1 = config_eth_account("user1")
- user_address_1 = user_1["address"]
- user_private_key_1 = decode_keyfile_json(
- raw_keyfile_json=user_1["keyfile_json"], password="password".encode("utf-8")
- )
- user_2 = config_eth_account("user2")
- user_address_2 = user_2["address"]
- user_private_key_2 = decode_keyfile_json(
- raw_keyfile_json=user_2["keyfile_json"], password="password".encode("utf-8")
- )
-
- # prepare data
- # Account
- _account = Account()
- _account.issuer_address = issuer_address
- _account.keyfile = issuer["keyfile_json"]
- _account.eoa_password = E2EEUtils.encrypt("password")
- _account.rsa_private_key = issuer["rsa_private_key"]
- _account.rsa_public_key = issuer["rsa_public_key"]
- _account.rsa_passphrase = E2EEUtils.encrypt("password")
- _account.rsa_status = AccountRsaStatus.SET.value
- db.add(_account)
-
- # Token
- personal_info_contract_address = deploy_personal_info_contract(
- issuer_address, issuer_private_key
- )
- await set_personal_info_contract(
- db,
- personal_info_contract_address,
- _account,
- [
- {
- "address": user_address_1,
- "private_key": user_private_key_1,
- "data": {
- "name": "name_test_con_1",
- "address": "address_test_con_1",
- },
- },
- {
- "address": user_address_2,
- "private_key": user_private_key_2,
- "data": {
- "name": "name_test_con_2",
- "address": "address_test_con_2",
- },
- },
- ],
- )
- token_address_1 = await deploy_bond_token_contract(
- issuer_address, issuer_private_key, personal_info_contract_address
- )
- _token_1 = Token()
- _token_1.type = TokenType.IBET_STRAIGHT_BOND.value
- _token_1.tx_hash = ""
- _token_1.issuer_address = issuer_address
- _token_1.token_address = token_address_1
- _token_1.abi = {}
- _token_1.version = TokenVersion.V_23_12
- db.add(_token_1)
-
- # IDXPersonalInfo(only user_1)
- _idx_personal_info_1 = IDXPersonalInfo()
- _idx_personal_info_1.account_address = user_address_1
- _idx_personal_info_1.issuer_address = issuer_address
- _idx_personal_info_1.personal_info = {
- "name": "name_test_db_1",
- "address": "address_test_db_1",
- }
- db.add(_idx_personal_info_1)
-
- # UTXO
- # user_1: "2022/01/01" = 100 + 10, "2022/01/02" = 30 + 40
- # user_2: "2022/01/01" = 200 + 20, "2022/01/02" = 40 + 2
- _utxo_1 = UTXO()
- _utxo_1.transaction_hash = "tx1"
- _utxo_1.account_address = user_address_1
- _utxo_1.token_address = token_address_1
- _utxo_1.amount = 100
- _utxo_1.block_number = 1
- _utxo_1.block_timestamp = datetime.strptime(
- "2021/12/31 15:20:30", "%Y/%m/%d %H:%M:%S"
- ) # JST 2022/01/01
- db.add(_utxo_1)
-
- _utxo_2 = UTXO()
- _utxo_2.transaction_hash = "tx2"
- _utxo_2.account_address = user_address_1
- _utxo_2.token_address = token_address_1
- _utxo_2.amount = 10
- _utxo_2.block_number = 2
- _utxo_2.block_timestamp = datetime.strptime(
- "2022/01/01 01:20:30", "%Y/%m/%d %H:%M:%S"
- ) # JST 2022/01/01
- db.add(_utxo_2)
-
- _utxo_3 = UTXO()
- _utxo_3.transaction_hash = "tx3"
- _utxo_3.account_address = user_address_1
- _utxo_3.token_address = token_address_1
- _utxo_3.amount = 30
- _utxo_3.block_number = 3
- _utxo_3.block_timestamp = datetime.strptime(
- "2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"
- ) # JST 2022/01/02
- db.add(_utxo_3)
-
- _utxo_4 = UTXO()
- _utxo_4.transaction_hash = "tx4"
- _utxo_4.account_address = user_address_1
- _utxo_4.token_address = token_address_1
- _utxo_4.amount = 40
- _utxo_4.block_number = 4
- _utxo_4.block_timestamp = datetime.strptime(
- "2022/01/02 01:20:30", "%Y/%m/%d %H:%M:%S"
- ) # JST 2022/01/02
- db.add(_utxo_4)
-
- _utxo_5 = UTXO()
- _utxo_5.transaction_hash = "tx5"
- _utxo_5.account_address = user_address_2
- _utxo_5.token_address = token_address_1
- _utxo_5.amount = 200
- _utxo_5.block_number = 5
- _utxo_5.block_timestamp = datetime.strptime(
- "2021/12/31 15:20:30", "%Y/%m/%d %H:%M:%S"
- ) # JST 2022/01/01
- db.add(_utxo_5)
-
- _utxo_6 = UTXO()
- _utxo_6.transaction_hash = "tx6"
- _utxo_6.account_address = user_address_2
- _utxo_6.token_address = token_address_1
- _utxo_6.amount = 20
- _utxo_6.block_number = 6
- _utxo_6.block_timestamp = datetime.strptime(
- "2022/01/01 01:20:30", "%Y/%m/%d %H:%M:%S"
- ) # JST 2022/01/01
- db.add(_utxo_6)
-
- _utxo_7 = UTXO()
- _utxo_7.transaction_hash = "tx7"
- _utxo_7.account_address = user_address_2
- _utxo_7.token_address = token_address_1
- _utxo_7.amount = 40
- _utxo_7.block_number = 7
- _utxo_7.block_timestamp = datetime.strptime(
- "2022/01/01 15:20:30", "%Y/%m/%d %H:%M:%S"
- ) # JST 2022/01/02
- db.add(_utxo_7)
-
- _utxo_8 = UTXO()
- _utxo_8.transaction_hash = "tx8"
- _utxo_8.account_address = user_address_2
- _utxo_8.token_address = token_address_1
- _utxo_8.amount = 2
- _utxo_8.block_number = 8
- _utxo_8.block_timestamp = datetime.strptime(
- "2022/01/02 01:20:30", "%Y/%m/%d %H:%M:%S"
- ) # JST 2022/01/02
- db.add(_utxo_8)
-
- # Template
-
- # Template
- _template = LedgerTemplate()
- _template.token_address = token_address_1
- _template.issuer_address = issuer_address
- _template.token_name = "受益権テスト"
- _template.headers = [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "テスト項目1": "テスト値1",
- "テスト項目2": {
- "テスト項目A": "テスト値2A",
- "テスト項目B": "テスト値2B",
- },
- "テスト項目3": {
- "テスト項目A": {"テスト項目a": "テスト値3Aa"},
- "テスト項目B": "テスト値3B",
- },
- },
- ]
- _template.footers = [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "f-テスト項目1": "f-テスト値1",
- "f-テスト項目2": {
- "f-テスト項目A": "f-テスト値2A",
- "f-テスト項目B": "f-テスト値2B",
- },
- "f-テスト項目3": {
- "f-テスト項目A": {"f-テスト項目a": "f-テスト値3Aa"},
- "f-テスト項目B": "f-テスト値3B",
- },
- },
- ]
- db.add(_template)
-
- # Template Details 1
- _details_1 = LedgerDetailsTemplate()
- _details_1.token_address = token_address_1
- _details_1.token_detail_type = "優先受益権"
- _details_1.headers = [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "test項目1": "test値1",
- "test項目2": {
- "test項目A": "test値2A",
- },
- },
- ]
- _details_1.footers = [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "test-item1": "test-value1",
- "test-item2": {"test-itemA": {"test-itema": "test-value2Aa"}},
- },
- ]
- _details_1.data_type = LedgerDetailsDataType.IBET_FIN.value
- _details_1.data_source = token_address_1
- db.add(_details_1)
-
- # Template Details 2
- _details_2 = LedgerDetailsTemplate()
- _details_2.token_address = token_address_1
- _details_2.token_detail_type = "劣後受益権"
- _details_2.headers = [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "d-test項目1": "d-test値1",
- "d-test項目2": "d-test値2",
- },
- ]
- _details_2.footers = [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "f-d-test項目1": "d-test値1",
- "f-d-test項目2": "d-test値2",
- },
- ]
- _details_2.data_type = LedgerDetailsDataType.DB.value
- _details_2.data_source = "data_id_2"
- db.add(_details_2)
-
- # Details 2 Data
- _details_2_data_1 = LedgerDetailsData()
- _details_2_data_1.token_address = token_address_1
- _details_2_data_1.data_id = "data_id_2"
- _details_2_data_1.name = "test_data_name_1"
- _details_2_data_1.address = "test_data_address_1"
- _details_2_data_1.amount = 100
- _details_2_data_1.price = 200
- _details_2_data_1.balance = 20000
- _details_2_data_1.acquisition_date = "2022/03/03"
- db.add(_details_2_data_1)
-
- _details_2_data_2 = LedgerDetailsData()
- _details_2_data_2.token_address = token_address_1
- _details_2_data_2.data_id = "data_id_2"
- _details_2_data_2.name = "test_data_name_2"
- _details_2_data_2.address = "test_data_address_2"
- _details_2_data_2.amount = 30
- _details_2_data_2.price = 40
- _details_2_data_2.balance = 1200
- _details_2_data_2.acquisition_date = "2022/12/03"
- db.add(_details_2_data_2)
-
- db.commit()
-
- # Execute
- await ledger_utils.create_ledger(token_address_1, async_db)
- await async_db.commit()
- await async_db.close()
-
- # assertion
- _notifications = db.scalars(select(Notification)).all()
- assert len(_notifications) == 1
- _notification = db.scalars(select(Notification).limit(1)).first()
- assert _notification.id == 1
- assert _notification.notice_id is not None
- assert _notification.issuer_address == issuer_address
- assert _notification.priority == 0
- assert _notification.type == NotificationType.CREATE_LEDGER_INFO
- assert _notification.code == 0
- assert _notification.metainfo == {
- "token_address": token_address_1,
- "token_type": TokenType.IBET_STRAIGHT_BOND.value,
- "ledger_id": 1,
- }
- _ledger = db.scalars(select(Ledger).limit(1)).first()
- assert _ledger.id == 1
- assert _ledger.token_address == token_address_1
- assert _ledger.token_type == TokenType.IBET_STRAIGHT_BOND.value
- now_ymd = datetime.now(pytz.timezone(TZ)).strftime("%Y/%m/%d")
- assert _ledger.ledger == {
- "created": now_ymd,
- "token_name": "受益権テスト",
- "currency": "JPY",
- "headers": [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "テスト項目1": "テスト値1",
- "テスト項目2": {
- "テスト項目A": "テスト値2A",
- "テスト項目B": "テスト値2B",
- },
- "テスト項目3": {
- "テスト項目A": {"テスト項目a": "テスト値3Aa"},
- "テスト項目B": "テスト値3B",
- },
- },
- ],
- "details": [
- {
- "token_detail_type": "優先受益権",
- "headers": [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "test項目1": "test値1",
- "test項目2": {
- "test項目A": "test値2A",
- },
- },
- ],
- "data": [
- {
- "account_address": user_address_2,
- "name": "name_test_con_2",
- "address": "address_test_con_2",
- "amount": 220,
- "price": 20,
- "balance": 220 * 20,
- "acquisition_date": "2022/01/01",
- },
- {
- "account_address": user_address_2,
- "name": "name_test_con_2",
- "address": "address_test_con_2",
- "amount": 42,
- "price": 20,
- "balance": 42 * 20,
- "acquisition_date": "2022/01/02",
- },
- {
- "account_address": user_address_1,
- "name": "name_test_db_1",
- "address": "address_test_db_1",
- "amount": 110,
- "price": 20,
- "balance": 110 * 20,
- "acquisition_date": "2022/01/01",
- },
- {
- "account_address": user_address_1,
- "name": "name_test_db_1",
- "address": "address_test_db_1",
- "amount": 70,
- "price": 20,
- "balance": 70 * 20,
- "acquisition_date": "2022/01/02",
- },
- ],
- "footers": [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "test-item1": "test-value1",
- "test-item2": {
- "test-itemA": {"test-itema": "test-value2Aa"}
- },
- },
- ],
- },
- {
- "token_detail_type": "劣後受益権",
- "headers": [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "d-test項目1": "d-test値1",
- "d-test項目2": "d-test値2",
- },
- ],
- "data": [
- {
- "account_address": None,
- "name": "test_data_name_1",
- "address": "test_data_address_1",
- "amount": 100,
- "price": 200,
- "balance": 20000,
- "acquisition_date": "2022/03/03",
- },
- {
- "account_address": None,
- "name": "test_data_name_2",
- "address": "test_data_address_2",
- "amount": 30,
- "price": 40,
- "balance": 1200,
- "acquisition_date": "2022/12/03",
- },
- ],
- "footers": [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "f-d-test項目1": "d-test値1",
- "f-d-test項目2": "d-test値2",
- },
- ],
- },
- ],
- "footers": [
- {
- "key": "aaa",
- "value": "bbb",
- },
- {
- "f-テスト項目1": "f-テスト値1",
- "f-テスト項目2": {
- "f-テスト項目A": "f-テスト値2A",
- "f-テスト項目B": "f-テスト値2B",
- },
- "f-テスト項目3": {
- "f-テスト項目A": {"f-テスト項目a": "f-テスト値3Aa"},
- "f-テスト項目B": "f-テスト値3B",
- },
- },
- ],
- }
- db.close()
-
- #
- # SKIP: Not Exist Template
- @pytest.mark.asyncio
- async def test_normal_3(self, db, async_db):
- issuer = config_eth_account("user5")
- issuer_address = issuer["address"]
- issuer_private_key = decode_keyfile_json(
- raw_keyfile_json=issuer["keyfile_json"], password="password".encode("utf-8")
- )
-
- # prepare data
- # Token
- token_address_1 = await deploy_bond_token_contract(
- issuer_address, issuer_private_key, ZERO_ADDRESS
- )
- _token_1 = Token()
- _token_1.type = TokenType.IBET_STRAIGHT_BOND.value
- _token_1.tx_hash = ""
- _token_1.issuer_address = issuer_address
- _token_1.token_address = token_address_1
- _token_1.abi = {}
- _token_1.version = TokenVersion.V_23_12
- db.add(_token_1)
- db.commit()
-
- # Execute
- await ledger_utils.create_ledger(token_address_1, async_db)
- await async_db.commit()
- await async_db.close()
-
- # assertion
- _notifications = db.scalars(select(Notification)).all()
- assert len(_notifications) == 0
- _ledger = db.scalars(select(Ledger).limit(1)).first()
- assert _ledger is None
- db.close()
-
- #
- # SKIP: Other Token Type
- @pytest.mark.asyncio
- async def test_normal_4(self, db, async_db):
- issuer = config_eth_account("user5")
- issuer_address = issuer["address"]
- issuer_private_key = decode_keyfile_json(
- raw_keyfile_json=issuer["keyfile_json"], password="password".encode("utf-8")
- )
-
- # prepare data
- # Token
- token_address_1 = await deploy_bond_token_contract(
- issuer_address, issuer_private_key, ZERO_ADDRESS
- )
- _token_1 = Token()
- _token_1.type = "IbetCoupon"
- _token_1.tx_hash = ""
- _token_1.issuer_address = issuer_address
- _token_1.token_address = token_address_1
- _token_1.abi = {}
- _token_1.version = TokenVersion.V_22_12
- db.add(_token_1)
-
- db.commit()
-
- # Execute
- await ledger_utils.create_ledger(token_address_1, async_db)
- await async_db.commit()
- await async_db.close()
-
- # assertion
- _notifications = db.scalars(select(Notification)).all()
- assert len(_notifications) == 0
- _ledger = db.scalars(select(Ledger).limit(1)).first()
- assert _ledger is None
- db.close()
-
- ###########################################################################
- # Error Case
- ###########################################################################