Code Monkey home page Code Monkey logo

Comments (13)

eprbell avatar eprbell commented on May 31, 2024 2

BTW, the RP2 error message was a bit cryptic: I improved it and now it should be easier to understand.

from rp2.

eprbell avatar eprbell commented on May 31, 2024 1

Yes, it's a problem with Coinbase REST data. Let's close the issue. Thanks for reporting!

from rp2.

eprbell avatar eprbell commented on May 31, 2024

The error is saying that total crypto in < total crypto out. If you sum the 3 crypto in entries you get 1.3031783, which is less than the amount disposed of in the out transaction (1.30317832). Could you check on the Coinbase-generated CSV files and verify the following:

  • do you have a total of 4 LRC transactions?
  • do the LRC crypto in/out values match with those in the ODS file?

from rp2.

jameskupke avatar jameskupke commented on May 31, 2024

Here's the 4 raw transactions.

XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX Reward 2021-11-04T00:49:31Z LRC 0.434896059841698 0.5005436087475 Coinbase
XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX Reward 2021-11-04T00:50:20Z LRC 0.433783021732529 0.499110742812 Coinbase
XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX Reward 2021-11-04T00:50:50Z LRC 0.434499239626331 0.499934814038 Coinbase
XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX Converted from 2021-11-04T00:51:21Z         LRC 1.30317832 1.499827928488
XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX Converted to 2021-11-04T00:51:22Z XTZ 0.235629 1.499827928488 Coinbase      

So, it looks like there's a few more digits in the raw transactions vs. what the ODS outputted, so it seems like a rounding issue?

from rp2.

eprbell avatar eprbell commented on May 31, 2024

This is from the Coinbase CSV, correct? The next step is to look for these 4 transactions in the DaLI debug log: this will show us what numbers Coinbase is putting out via the REST API. Definitely looks like a rounding issue, but looking at the REST output from the debug log will tell us who's rounding incorrectly (DaLI or Coinbase).

from rp2.

jameskupke avatar jameskupke commented on May 31, 2024

Yes, the above post was the Coinbase CSV.

Here's the DEBUG logs:

2022-04-03 07:34:25,455/dali/DEBUG: Self-contained transaction: InTransaction:
  plugin=Coinbase
  unique_id=AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA
  raw_data={"id": "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA", "type": "send", "status": "completed", "amount": {"amount": "0.43449923", "currency": "LRC"}, "native_amount": {"amount": "0.50", "currency": "USD"}, "description": "Earn Task", "created_at": "2021-11-04T00:50:50Z", "updated_at": "2021-11-04T00:50:50Z", "resource": "transaction", "resource_path": "/v2/accounts/AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA/transactions/AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA", "instant_exchange": false, "off_chain_status": "completed", "network": {"status": "off_blockchain", "status_description": null}, "from": {"id": "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA", "resource": "user", "resource_path": "/v2/users/AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA", "currency": "LRC"}, "details": {"title": "Received Loopring", "subtitle": "From Coinbase Earn", "header": "Received 0.43449923 LRC ($0.50)", "health": "positive"}, "hide_native_amount": false}
  timestamp=2021-11-04 00:50:50 +0000
  asset=LRC
  exchange=Coinbase
  holder=(name)
  transaction_type=Income
  spot_price=1.150750025494866814838774283
  crypto_in=0.43449923
  fiat_fee=0
  fiat_in_no_fee=0.50
  fiat_in_with_fee=0.50
  notes=Coinbase EARN; Received Loopring
2022-04-03 07:34:25,455/dali/DEBUG: Self-contained transaction: InTransaction:
  plugin=Coinbase
  unique_id=AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA
  raw_data={"id": "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA", "type": "send", "status": "completed", "amount": {"amount": "0.43378302", "currency": "LRC"}, "native_amount": {"amount": "0.50", "currency": "USD"}, "description": "Earn Task", "created_at": "2021-11-04T00:50:20Z", "updated_at": "2021-11-04T00:50:20Z", "resource": "transaction", "resource_path": "/v2/accounts/AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA/transactions/AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA", "instant_exchange": false, "off_chain_status": "completed", "network": {"status": "off_blockchain", "status_description": null}, "from": {"id": "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA", "resource": "user", "resource_path": "/v2/users/AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA", "currency": "LRC"}, "details": {"title": "Received Loopring", "subtitle": "From Coinbase Earn", "header": "Received 0.43378302 LRC ($0.50)", "health": "positive"}, "hide_native_amount": false}
  timestamp=2021-11-04 00:50:20 +0000
  asset=LRC
  exchange=Coinbase
  holder=(name)
  transaction_type=Income
  spot_price=1.152650004603684118387114369
  crypto_in=0.43378302
  fiat_fee=0
  fiat_in_no_fee=0.50
  fiat_in_with_fee=0.50
  notes=Coinbase EARN; Received Loopring
2022-04-03 07:34:25,455/dali/DEBUG: Self-contained transaction: InTransaction:
  plugin=Coinbase
  unique_id=AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA
  raw_data={"id": "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA", "type": "send", "status": "completed", "amount": {"amount": "0.43489605", "currency": "LRC"}, "native_amount": {"amount": "0.50", "currency": "USD"}, "description": "Earn Task", "created_at": "2021-11-04T00:49:31Z", "updated_at": "2021-11-04T00:49:31Z", "resource": "transaction", "resource_path": "/v2/accounts/AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA/transactions/AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA", "instant_exchange": false, "off_chain_status": "completed", "network": {"status": "off_blockchain", "status_description": null}, "from": {"id": "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA", "resource": "user", "resource_path": "/v2/users/AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA", "currency": "LRC"}, "details": {"title": "Received Loopring", "subtitle": "From Coinbase Earn", "header": "Received 0.43489605 LRC ($0.50)", "health": "positive"}, "hide_native_amount": false}
  timestamp=2021-11-04 00:49:31 +0000
  asset=LRC
  exchange=Coinbase
  holder=(name)
  transaction_type=Income
  spot_price=1.149700026017711588780813254
  crypto_in=0.43489605
  fiat_fee=0
  fiat_in_no_fee=0.50
  fiat_in_with_fee=0.50
  notes=Coinbase EARN; Received Loopring
2022-04-03 07:34:25,455/dali/DEBUG: Self-contained transaction: OutTransaction:
  plugin=Coinbase
  unique_id=AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA
  raw_data={"id": "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA", "type": "trade", "status": "completed", "amount": {"amount": "-1.30317832", "currency": "LRC"}, "native_amount": {"amount": "-1.50", "currency": "USD"}, "description": null, "created_at": "2021-11-04T00:51:21Z", "updated_at": "2021-11-04T00:51:21Z", "resource": "transaction", "resource_path": "/v2/accounts/AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA/transactions/AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA", "instant_exchange": false, "trade": {"id": "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA", "resource": "trade", "resource_path": "/v2/accounts/AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA/trades/AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA"}, "details": {"title": "Converted from Loopring", "subtitle": "Using LRC Wallet", "header": "Converted 1.30317832 LRC ($1.50)", "health": "positive", "payment_method_name": "LRC Wallet"}, "hide_native_amount": false}
  timestamp=2021-11-04 00:51:21 +0000
  asset=LRC
  exchange=Coinbase
  holder=(name)
  transaction_type=Sell
  spot_price=1.151032039882308662102359100
  crypto_out_no_fee=1.30317832
  crypto_fee=0E+27
  crypto_out_with_fee=1.30317832
  fiat_out_no_fee=1.50
  fiat_fee=0
  notes=Sell side of conversion of 1.30317832 LRC	

Looks like the 3 IN total to 1.3031783
The Out shows as: 1.30317832.

So it's off by −0.00000002

from rp2.

jameskupke avatar jameskupke commented on May 31, 2024

Now that I see that's the crypto values, I may have to just manually edit a few around to make sure that the rounding errors are corrected in the ODS.

from rp2.

eprbell avatar eprbell commented on May 31, 2024

Yes, looks like Coinbase is feeding us bad data via REST (though the error is really small)... :-( However it's interesting that they are generating their CSV file correctly: perhaps they have another version of the REST API they use only internally.

from rp2.

jameskupke avatar jameskupke commented on May 31, 2024

Yeah. I was able to generate the RP2 files after manually adjusting. Since I think this is a limitation on the REST API data, I don't think it's specifically an RP2 issue. I guess close this out?

from rp2.

heiden12 avatar heiden12 commented on May 31, 2024

Is there a work around for this issue?

from rp2.

eprbell avatar eprbell commented on May 31, 2024

Unfortunately not... This is a Coinbase REST API bug, so there isn't a lot we can do about it. The only workaround would be to write a script to patch the ODS file before feeding it to RP2.

from rp2.

eprbell avatar eprbell commented on May 31, 2024

Here's something hacky I put together a while ago for testing purposes. With a few modifications you should be able to use it to patch your file before feeding it to RP2:

# Copyright 2022 eprbell
#
# 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.

import sys

from argparse import ArgumentParser, Namespace, RawTextHelpFormatter
from configparser import ConfigParser
from pathlib import Path
from typing import Any, Dict

import ezodf

from dali.dali_configuration import DEFAULT_CONFIGURATION, Keyword, is_builtin_section_name
from dali.dali_main import _validate_header_configuration
from rp2.rp2_decimal import CRYPTO_DECIMALS

_VERSION: str = "0.0.1"


def main() -> None:

    args: Namespace
    parser: ArgumentParser

    dali_configuration: Dict[str, Any] = DEFAULT_CONFIGURATION

    parser = _setup_argument_parser()
    args = parser.parse_args()

    ini_config: ConfigParser = ConfigParser()
    ini_config.read(args.ini_file)
    
    for section_name in ini_config.sections():
        normalized_section_name: str = section_name.split(" ", 1)[0]
        if is_builtin_section_name(normalized_section_name):
            if section_name != normalized_section_name:
                print("Builtin section '%s' cannot have extra trailing keywords: '%s'", normalized_section_name, section_name)
                sys.exit(1)
            if section_name in {Keyword.IN_HEADER.value, Keyword.OUT_HEADER.value, Keyword.INTRA_HEADER.value}:
                dali_configuration[section_name] = _validate_header_configuration(ini_config, section_name)
            continue

    print(f"File to patch: {args.file_to_patch}")

    _apply_patch(args.file_to_patch, dali_configuration)

def _setup_argument_parser() -> ArgumentParser:
    parser: ArgumentParser = ArgumentParser(
        description=(
            "Patch Dali output\n"
        ),
        formatter_class=RawTextHelpFormatter,
    )

    parser.add_argument(
        "-v",
        "--version",
        action="version",
        version=f"DaLI Output Patcher {_VERSION}",
        help="Print DaLI Output Patcher version",
    )
    parser.add_argument(
        "ini_file",
        action="store",
        help="INI file",
        metavar="INI_FILE",
        type=str,
    )

    parser.add_argument(
        "file_to_patch",
        action="store",
        help="Dali-generated ODS file to patch",
        metavar="FILE_TO_PATCH",
        type=str,
    )

    return parser


def _apply_patch(file_to_patch: str, configuration: Dict[str, Any]) -> ArgumentParser:
    file_to_patch_path: Path = Path(file_to_patch)
    if not file_to_patch_path.exists():
        return f"Error: {file_to_patch} does not exist"

    ods_file: Any = ezodf.opendoc(str(file_to_patch_path))
    sheet: Any

    for sheet in ods_file.sheets:
        if sheet.name == "ETH":

            row_count: int = 0
            row: Any = None
            for row_count, row in enumerate(sheet.rows()):
                if row[configuration["in_header"]["unique_id"]].value == "<...snip>"
                    print(f"{row_count}: Row to patch (before): {_row_as_string(row)}")
                    sheet[row_count, configuration["in_header"]["fiat_fee"]].set_value(14.18)
                    sheet[row_count, configuration["in_header"]["fiat_in_with_fee"]].set_value(1728)
                    print(f"{row_count}: Row to patch (after):  {_row_as_string(row)}")

    ods_file.save()

def _row_as_string(row: Any) -> str:
    values: List[str] = []
    cell: Any
    for cell in row:
        value: Any = str(_parse_cell_value(cell))
        values.append(value)

    # Remove trailing whitespace from row
    i: int
    for i in range(len(values) - 1, -1, -1):
        if not values[i]:
            del values[i]
        else:
            break

    return ",".join(values)

def _parse_cell_value(cell: Any) -> Any:
    value: Any
    try:
        if cell.formula:
            value = cell.formula
        elif cell.value or cell.value == 0:
            value = round(float(cell.value), CRYPTO_DECIMALS)
            if value == -0.0:
                value = 0
        else:
            value = ""
    except ValueError:
        value = cell.value

    return value

                
if __name__ == "__main__":
    main()

from rp2.

jameskupke avatar jameskupke commented on May 31, 2024

Is there a work around for this issue?

I didn't have very complicated amount of transactions. (Multiple INs, and 1 OUT), so I ended up just SUM-ing the values to make it equal in the ODS file.

from rp2.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.