Coder Social home page Coder Social logo

omgnetwork / ewallet Goto Github PK

View Code? Open in Web Editor NEW
323.0 39.0 74.0 45.54 MB

eWallet Backend for the OmiseGO SDKs.

Home Page: https://omisego.network/

License: Apache License 2.0

Elixir 81.05% HTML 0.11% CSS 0.85% JavaScript 17.51% Dockerfile 0.04% Makefile 0.05% Shell 0.39%
omisego ewallet omg wallet loyalty-programs elixir

ewallet's Introduction

OmiseGO eWallet Server

OmiseGO eWallet Server is a server application in OmiseGO eWallet Suite that allows a provider (businesses or individuals) to setup and run their own digital wallet services through a local ledger, and to a decentralized blockchain exchange in the future to form a federated network on the OMG network allowing exchange of any currency into any other in a transparent way.

Getting started

The quickest way to get OmiseGO eWallet Server running on macOS and Linux is to use Docker-Compose.

  1. Install Docker and Docker-Compose

  2. Download OmiseGO eWallet Server's docker-compose.yml:

    curl -O -sSL https://raw.githubusercontent.com/omisego/ewallet/master/docker-compose.yml
  3. Create docker-compose.override.yml either manually or use this auto-configuration script:

    curl -O -sSL https://raw.githubusercontent.com/omisego/ewallet/master/docker-gen.sh
    chmod +x docker-gen.sh
    ./docker-gen.sh > docker-compose.override.yml
    
  4. Initialize the database and start the server:

    docker-compose run --rm ewallet initdb
    docker-compose run --rm ewallet seed
    docker-compose up -d
    

Encountered a problem during the installation? See the Setup Troubleshooting Guide.

For other platforms or a more advanced setup, see alternative installation below.

Alternative installation

Upgrade

See Upgrading the eWallet Server.

Commands

Docker image entrypoint is configured to recognize most commands that are used during normal operations. The way to invoke these commands depend on the installation method you choose.

  • In case of Docker-Compose, use docker-compose run --rm ewallet <command>
  • In case of Docker, use docker run -it --rm omisego/ewallet <command>
  • In case of bare metal, see also bare metal installation instruction.

initdb

For example:

  • docker-compose run --rm ewallet initdb (Docker-Compose)
  • docker run -it --rm omisego/ewallet:latest initdb (Docker)

These commands create the database if not already created, or upgrade them if necessary. This command is expected to be run every time you have upgraded the version of OmiseGO eWallet Suite.

seed

For example:

  • docker-compose run --rm ewallet seed (Docker-Compose)
  • docker run -it --rm omisego/ewallet:latest seed (Docker)

These commands create the initial data in the database. If seed is run without arguments, the command will seed initial data for production environment. The seed command may be configured to seed with other kind of seed data:

  • seed --sample will seed a sample data suitable for evaluating OmiseGO eWallet Server.
  • seed --e2e will seed a data for end-to-end testing.
  • seed --settings will seed the application settings for the OmiseGO eWallet Server.

config

For example:

  • docker-compose run --rm ewallet config <key> <value> (Docker-Compose)
  • docker run -it --rm omisego/ewallet:latest config <key> <value> (Docker)

These commands will update the configuration key (see also settings documentation) in the database. For some keys which require whitespace, such as gcs_credentials, you can prevent string splitting by putting them in a single or double-quote, e.g. config gcs_credentials "gcs configuration".

Documentation

All documentations can found in the docs directory. It is recommended to take a look at the documentation of the OmiseGO eWallet Server you are running.

API documentation

OmiseGO eWallet Server is meant to be run by the provider, and thus API documentation is available in the OmiseGO eWallet Server itself rather than as online documentation. You may review the API documentation at the following locations in the OmiseGO eWallet Server setup.

  • /api/admin/docs.ui for Admin API, used by server apps to manage tokens, accounts, transactions, global settings, etc.
  • /api/client/docs.ui for Client API, used by client apps to create transaction on behalf of user, user's settings, etc.

In case you want to explore the API documentation without installing the OmiseGO eWallet Server, you may use our OmiseGO eWallet Staging. Please note that OmiseGO eWallet Staging tracks development release and there might be API differences from the stable release.

SDKs

These are SDKs for integrating with the OmiseGO eWallet Server. For example, to integrate a loyalty point system built on OmiseGO eWallet Server into an existing system.

It is also possible to run OmiseGO eWallet Server in a standalone mode without needing to integrate into an existing system. These apps demonstrate the capabilities of the OmiseGO eWallet Server as a physical Point-of-Sale server and client.

Community Efforts

We are thankful to our community for creating and maintaining these wonderful works that we otherwise could not have done ourselves. If you have ported any part of the OmiseGO eWallet Server to another platform, we will be happy to list them here. Submit us a pull request.

Contributing

Contributing to the OmiseGO eWallet Server can be contributions to the code base, bug reports, feature suggestions or any sort of feedback. Please learn more from our contributing guide.

Support

The OmiseGO eWallet Server team closely monitors the following channels.

  • GitHub Issues: Browse or file a report for any bugs found
  • Gitter: Discuss features and suggestions in real-time
  • Stack Overflow: Search or create a new question with the tag omisego

If you need enterprise support or hosting solutions, please get in touch with us for more details.

License

The OmiseGO eWallet Server is licensed under the Apache License

ewallet's People

Contributors

0xkiwi avatar alainfonhof avatar cduangprom avatar dsdshcym avatar enyan94 avatar jarindr avatar jbunce avatar jimpeebles avatar jpopxfile avatar mederic-p avatar nicholasmueller avatar ripzery avatar sirn avatar unnawut avatar vanmil avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ewallet's Issues

AuthenticationTokenSchema after Login

AuthenticationTokenSchema

In Swagger the example response for a successful login in the AdminAPI has the following AuthenticationTokenSchema:

object string
authentication_token string
user_id string
user UserSchema
account_id string
account AccountSchema

But when I do an actual login it also returns the key master_admin bool. Is there a reason for this or is it missing from the example?

Your environment

Commit 169bf5c

RFC: Internal exchange mechanism

Simple Summary

Enables an eWallet server to perform exchanges and transfers from/to different minted tokens within its own eWallet environment.

Abstract

This RFC describes the standard endpoints, flows, request/response formats, error codes needed to allow an eWallet server to perform cross-token exchanges within its own eWallet environment.

It is expected that there will be following RFCs for exchanges across eWallet environments and across the OMG network.

Motivation

Prior to this RFC, the eWallet server is able to transfer values between accounts and/or users, if and only if the from and to are of the same minted token.

One of the main purposes of the eWallet is to enable exchanges of different minted tokens. Since, different mechanisms could be used and potentially impact future integrations with centralized & decentralized exchanges, it is important for this mechanism to be put up as an RFC and discussed before implementing.

Specification

Definitions

  • Internal exchange: An exchange transaction that happens within the same eWallet environment.

  • External exchange: An exchange transaction that involves a third-party, e.g. exchanging with a centralized or decentralized exchange services. The external exchange is out of scope of this RFC.

  • Exchange pair: A pair of minted tokens that are allowed to be exchanged.

  • Same-token transfer: A transaction whose its from_address and to_address are different, but from_token_uuid and to_token_uuid are the same.

  • Exchange transaction: A transaction whose its from_address and to_address are the same, but the from_token_uuid and to_token_uuid are different.

  • Exchange transfer: A transaction whose its from_address and to_address are different, and the from_token_uuid and to_token_uuid are also different.

Data schemas

EWalletDB.ExchangePair: Contains the data about a pair of minted tokens that are allowed to be exchanged.

  • from_minted_token (string)
  • to_minted_token (string)
  • rate (float)
  • reversible (boolean)
  • effective_at (datetime) - so the exchange rate can be set in advance

EWalletDB.Transfer: Contains the data about each transaction that happened.

  • To add:
    • from_amount (integer)
    • from_token_uuid (uuid)
    • to_amount (integer)
    • to_token_uuid (uuid)
    • metadata.exchange_rate (float, containing the exchange rate used for the transfer)
  • To migrate:
    • from_amount <- amount
    • from_token_uuid <- token_uuid
    • to_amount <- amount
    • to_token_uuid <- token_uuid
  • To remove:
    • amount (use from_amount and to_amount instead)
    • token_uuid (use from_token_uuid and to_token_uuid instead)

LocalLedgerDB.Transaction: A logical group of ledger entries that represents a single business event (e.g. a same-token transfer, an exchange transaction, an exchange transfer).

Each EWalletDB.Transfer item is one LocalLedgerDB.Transaction. One LocalLedgerDB.Transaction for an exchange has at least 4 LocalLedgerDB.Entry. For example:

  • transaction.type = “exchange”
  • transaction.metadata
    • exchange_pair_id
    • exchange_rate
    • exchange_reversed
  • transaction.entry[0], e.g. credit user 10 OMG
  • transaction.entry[1], e.g. debit exchange account 10 OMG
  • transaction.entry[2], e.g. credit exchange account 1 ETH
  • transaction.entry[3], e.g. debit user 1 ETH

Mechanisms

For internal exchanges, the operation happens at the DB's transaction level so it should be seamlessly handled within the eWallet server as long as the exchange operations are wrapped inside a single DB transaction.

At the API level, this can be represented as a typical /transfer endpoint, where the only difference is that for exchanges, the from_token_id and to_token_id have different values.

Same-token transfers (existing feature)

same-token transfer diagram

  1. Alice has 100 AAA
  2. Alice wants to send 10 AAA to Bob
  3. Alice sends 10 AAA to Bob
  4. Bob receives the 10 AAA from Alice

Example:

(Assuming subunit_to_unit = 1 for simplicity)

# EWalletDB.Transfer
{
  "id": "tfr_1234567890",
  "type": "internal",
  "from": "bal_alice_1111",
  "from_amount": 10,
  "from_token_id": "tok_AAA_1234",
  "to": "bal_bob_2222",
  "to_amount": 10,
  "to_token_id": "tok_AAA_1234"
}

# LocalLedgerDB.Transaction
{
  "uuid": "44d7fc38-b250-4456-a4e8-0d23dc52f310",
}

# LocalLedgerDB.Entry
[
  {
    "transaction_uuid": "44d7fc38-b250-4456-a4e8-0d23dc52f310",
    "type": "debit",
    "amount": 10,
    "wallet_address": "bal_alice_1111",
    "token_id": "tok_AAA_1234"
  },
  {
    "transaction_uuid": "44d7fc38-b250-4456-a4e8-0d23dc52f310",
    "type": "credit",
    "amount": 10,
    "wallet_address": "bal_bob_2222",
    "token_id": "tok_AAA_1234"
  }
]

Exchange transaction (proposed by this RFC)

This is when a user wants to exchange a token for another, where the sender and the receiver is the same address.

exchange transaction diagram

  1. Alice has 100 AAA
  2. Alice wants to exchange 10 AAA for 1 BBB with ExchangeAccount
  3. Alice sends 10 AAA to ExchangeAccount
  4. ExchangeAccount sends 1 BBB to Alice
  5. If 3. or 4. fails, the transaction is reverted

Example:

(Assuming subunit_to_unit = 1 for simplicity)

# EWalletDB.Transfer
{
  "id": "tfr_1234567890",
  "type": "exchange",
  "from": "bal_alice_1111",
  "from_amount": 10,
  "from_token_id": "tok_AAA_1234",
  "to": "bal_alice_1111",
  "to_amount": 1,
  "to_token_id": "tok_BBB_1234"
}

# LocalLedgerDB.Transaction
{
  "uuid": "44d7fc38-b250-4456-a4e8-0d23dc52f310",
}

# LocalLedgerDB.Entry
[
  {
    "transaction_uuid": "44d7fc38-b250-4456-a4e8-0d23dc52f310",
    "type": "debit",
    "amount": 10,
    "wallet_address": "bal_alice_1111",
    "token_id": "tok_AAA_1234"
  },
  {
    "transaction_uuid": "44d7fc38-b250-4456-a4e8-0d23dc52f310",
    "type": "credit",
    "amount": 10,
    "wallet_address": "bal_exchange_2222",
    "token_id": "tok_AAA_1234"
  },
  {
    "transaction_uuid": "44d7fc38-b250-4456-a4e8-0d23dc52f310",
    "type": "debit",
    "amount": 1,
    "wallet_address": "bal_exchange_2222",
    "token_id": "tok_BBB_1234"
  },
  {
    "transaction_uuid": "44d7fc38-b250-4456-a4e8-0d23dc52f310",
    "type": "credit",
    "amount": 1,
    "wallet_address": "bal_alice_1111",
    "token_id": "tok_BBB_1234"
  }
]

Exchange transfers (proposed by this RFC)

This is when a sender wants to transfer a token and expects the receiver at a different address to receive a different token.

exchange transfer diagram

  1. Alice has 100 AAA
  2. Alice wants to send 1 BBB to Bob using his/her funds of 100 AAA via ExchangeAccount that has liquidity
  3. Bob receives the 10 OMG from Alice (via ExchangeAccount)

Example:

(Assuming subunit_to_unit = 1 for simplicity)

# EWalletDB.Transfer
{
  "id": "tfr_1234567890",
  "type": "exchange_transfer",
  "from": "bal_alice_1111",
  "from_amount": 10,
  "from_token_id": "tok_AAA_1234",
  "to": "bal_bob_2222",
  "to_amount": 1,
  "to_token_id": "tok_BBB_1234"
}

# LocalLedgerDB.Transaction
{
  "uuid": "44d7fc38-b250-4456-a4e8-0d23dc52f310",
}

# LocalLedgerDB.Entry
[
  {
    "transaction_uuid": "44d7fc38-b250-4456-a4e8-0d23dc52f310",
    "type": "debit",
    "amount": 10,
    "wallet_address": "bal_alice_1111",
    "token_id": "tok_AAA_1234"
  },
  {
    "transaction_uuid": "44d7fc38-b250-4456-a4e8-0d23dc52f310",
    "type": "credit",
    "amount": 10,
    "wallet_address": "bal_exchange_3333",
    "token_id": "tok_AAA_1234"
  },
  {
    "transaction_uuid": "44d7fc38-b250-4456-a4e8-0d23dc52f310",
    "type": "debit",
    "amount": 1,
    "wallet_address": "bal_exchange_3333",
    "token_id": "tok_BBB_1234"
  },
  {
    "transaction_uuid": "44d7fc38-b250-4456-a4e8-0d23dc52f310",
    "type": "credit",
    "amount": 1,
    "wallet_address": "bal_bob_2222",
    "token_id": "tok_BBB_1234"
  }
]

Rounding method

The rounding method to use is "Round half to even", or the banker's rounding.

Exchange rates

Transactions are always made with the exchange amounts, not the rate. Although an exchange transaction is based on the exchange rate, the parties agree on the exchanging amounts, not the rate. This is important because the division remainders and the rounding will almost always cause the exchanging parties to get more or less tokens depending on the rounding method used.

Consequently, the UI must display the exchanging amounts and asks user to confirm the amount, not the rate. The rate can be displayed as a complimenting information.

/exchange.calculate endpoint

Calculate the amount of minted tokens to be exchanged, used for confirming the exact amount with the user before executing the actual exchange.

  • Use this endpoint to avoid discrepancies between how endpoint consumer and the server calculates the exchange amount.
  • Errors are returned if it is anticipated to happen in an actual transfer.

Request

Fields

  • from_amount (integer, optional)
  • from_token_id (string, required)
  • to_amount (integer, optional)
  • to_token_id (string, required)
Conditions
  • If from_amount is provided, to_amount will be calculated based on the exchange rate and rounding method.
  • If to_amount is provided, from_amount will be calculated based on the exchange rate and rounding method.
  • If both from_amount and to_amount are provided, and the amounts are the same as the server's calculation, a successful response is returned.
  • If both from_amount and to_amount are provided, but the amounts are different from the server's calculation, an exchange:invalid_rate response is returned.

Example

{
  "from_amount": 100,
  "from_token_id": "tok_AAA_1234",
  "to_amount": 100,
  "to_token_id": "tok_BBB_1234"
}

Response

{
  "version": "1",
  "success": true,
  "data": {
    "object": "exchange_calculation",
    "from_amount": 100,
    "from_token_id": "tok_AAA_1234",
    "to_amount": 100,
    "to_token_id": "tok_BBB_1234",
    "exchange_pair": "exg_AAA_BBB_123456",
    "exchange_rate": "1.00",
    "exchange_reversed": false
  }
}

/transfer endpoint

Exchange a certain amount of minted tokens between two addresses.

Request

Fields

  • from_amount (integer, optional)
  • from_token_id (string, required)
  • from_address (string, required)
  • to_amount (integer, optional)
  • to_token_id (string, required)
  • to_address (string, required)
  • exchange_account_id (string, optional)

The request may be sent without from_amount or to_amount and subjects to the same conditions as /exchange.calculate.

If the exchange_account_id is not provided, the exchange will be performed with the master account.

Example

{
  "from_token_id": "tok_AAA_1234",
  "from_address": "81e75f46-ee14-4e4c-a1e5-cddcb26dce9c",
  "to_amount": 100,
  "to_token_id": "tok_BBB_1234",
  "to_address": "4aa07691-2f99-4cb1-b36c-50763e2d2ba8",
  "exchange_account_id": "acc_01ca2p8jqans5aty5gj5etmjcf",
  "metadata": {},
  "encrypted_metadata": {}
}

Response

Use the current response format (returns a list of affected wallets).

Error codes

  • transaction:insufficient_funds - when requestor does not have enough funds to exchange.
  • exchange:insufficient_funds - when the counterparty does not have enough funds to exchange back. It is important to distinguish between the user and the counterparty so that user-friendly error message can be displayed, and the user knows if its the counterparty's funds or theirs that is insufficient.
  • exchange:pair_not_found - when request requires an exchange pair that does not exist.
  • exchange:pair_not_reversible - when request requires an exchange pair that exists, but the pair does not allow to be exchanged in the opposite direction.
  • exchange:invalid_rate - when the provided exchange amounts or the exchange rate is invalid.

Rationale

  1. Round-half-to-even or banker's rounding is used as it is commonly used in financial systems. It is also the default rounding mode for IEEE 754 (IEEE Standard for Floating-Point Arithmetic).

  2. The exchange account defaults to the master account (the top-level account) for ease of use. However, for larger use cases, it's expected that an exchange_account_id is provided as it's probably not ideal for all exchange transactions to go through the master account (for separation of concerns and accountability). This exchange_account_id would also allow for more use cases, e.g. dedicate an account as the exchange account and put funds in there. It is then possible to limit the amount of tokens that can be exchanged by limiting the funds that the account has.

  3. This RFC chose to reuse the /transfer endpoint because of its similarities to an exchange transaction and exchange transfer. An exchange transaction is basically a transfer of different tokens to the same address, while an exchange transfer can be represented by a transfer that has different from/to tokens.

  4. There could be a discrepancy between the time /exchange.calculate is made and when /transfer happens. Given that this is an internal exchange and exchange rates are fixed, unchanged for most of the time. The discrepancy will be very rare to occur.

References

Mostly from internal discussions. Any suggestions for the references (either for or against this RFC) is appreciated.

Endpoint /transactions.all test is randomly failing

Subject of the issue

  1) test /transactions.all returns all the transactions (EWalletAPI.V1.TransactionControllerTest)
     test/ewallet_api/v1/controllers/transaction_controller_test.exs:42
     Assertion with == failed
     code:  assert Enum.map(response["data"]["data"], fn t -> t["id"] end) == [meta.transfer_1().id(), meta.transfer_2().id(), meta.transfer_3().id(), meta.transfer_4().id(), meta.transfer_5().id(), meta.transfer_6().id(), meta.transfer_7().id(), meta.transfer_8().id()]
     left:  ["a6c65166-7694-476e-b031-5879f97ce60e",
             "3b38eb21-d483-4f58-ba67-68e8e2f04ad1",
             "2b23faf0-c724-4ded-9764-438fba02eb69",
             "2f2816d2-e60f-4a57-a8be-85e8bbf7e90c",
             "c18165f0-18e7-405c-b825-99a2497c0774",
             "b83cc2e9-8285-4970-a4dd-f52c2e96fca9",
             "5ab273af-861e-4b26-8f36-8d4fbb27c210",
             "6129e74e-86cc-4fb2-ae9b-d94b350b7000"]
     right: ["2b23faf0-c724-4ded-9764-438fba02eb69",
             "2f2816d2-e60f-4a57-a8be-85e8bbf7e90c",
             "c18165f0-18e7-405c-b825-99a2497c0774",
             "b83cc2e9-8285-4970-a4dd-f52c2e96fca9",
             "5ab273af-861e-4b26-8f36-8d4fbb27c210",
             "6129e74e-86cc-4fb2-ae9b-d94b350b7000",
             "a6c65166-7694-476e-b031-5879f97ce60e",
             "3b38eb21-d483-4f58-ba67-68e8e2f04ad1"]
     stacktrace:
       test/ewallet_api/v1/controllers/transaction_controller_test.exs:48: (test)

Your environment

Jenkins, CI

Steps to reproduce

Run the test few times.

Expected behavior

Not randomly failing

Actual behavior

Randomly failing

Improve project README

The current README for the project is a little big overwhelming to get started. I believe the user will benefit greatly if we simplify the README to just topic user will first look for, and link to a more advanced topics in the docs/ directory.

Here's some example of a project I stumbled upon that has a great README or something we could take hint from:

  • FoundationDB — very concise and clear, and has everything I want to know about the project at a glance. I especially like the "Compiling from source" which is loosely written, but very easy to follow.
  • Milksnake — this is organized in a "Why", "What", and "How" which I like. I think making the heading a question make it easy to focus on explaining a single thing, and it coincides nicely with the user's expectation of the README in the first place, e.g. if we have "How to install?" section for when user look for how to install.
  • Re-frame — a bit different from what I'm proposing for README, and it's more of an article, but the framework require full understanding of the concept and the author did a great job putting all pieces together that you'd be able to use it immediately after finished reading the README.

Feel free to add more examples.

Add GraphicsMagick support

We should support GraphicsMagick in addition to ImageMagick. GraphicsMagick has a much lighter footprint, uses less resource, and likely cover all features we want (resizing images). It also has mostly compatible API with ImageMagick. We should only need to prefix existing ImageMagick invocation with gm.

mix seed shouldn't error if the BASE_URL wasn't set

Subject of the issue

mix seed shouldn't error if the BASE_URL wasn't set.

Your environment

$ uname -a
Linux srv1 4.4.86+ #1 SMP Thu Dec 7 20:11:11 PST 2017 x86_64 GNU/Linux

Steps to reproduce

Leave out BASE_URL when running mix seed

Expected behavior

Seed works with URL fallback to example.com or something.

Actual behavior

Without BASE_URL:

$ env |grep ^BASE_URL
$ mix seed
** (ArgumentError) argument error
    apps/ewallet/priv/repo/report_minimum.exs:5: (file)
    (elixir) lib/code.ex:334: Code.load_file/2

With BASE_URL:

$ env BASE_URL=http://www.example.com/ mix seed
...snip...
Database seeding completed. Enjoy!

/minted_token.create fails with "client:invalid_parameter" error

Minted token create request error

Creating minted tokens response returns that the request is bad. I have tried in swagger, admin panel and go. Even though I am using the default parameters it results in the following response:

{
  "version": "1",
  "success": false,
  "data": {
    "object": "error",
    "messages": null,
    "description": "Invalid parameter provided",
    "code": "client:invalid_parameter"
  }
}

Your environment

I am on commit 169bf5c.

Steps to reproduce

Parameters:

{
  "symbol": "BTC",
  "name": "Bitcoin",
  "description": "desc",
  "subunit_to_unit": 100
}

mix seed fails with "(ArgumentError) argument error"

Mix seed

Running mix seed caused an Argument error.

Environment

  • Node v8.11.1
  • Yarn v1.6
  • Elixir v1.6.5
  • Erlang 20

Steps to reproduce

I installed all dependencies with brew and followed all the steps in Setting up. After pressing Enter to start seeding the following error is shown:

** (ArgumentError) argument error
    :erlang.bit_size(%EWalletDB.AuthToken{__meta__: #Ecto.Schema.Metadata<:loaded, "auth_token">, account: #Ecto.Association.NotLoaded<association :account is not loaded>, account_uuid: "d5b1eb7e-1397-4e8e-8531-0b6dfe166438", expired: nil, id: "atk_01cczydqdxtpawt0jxax5k8m5c", inserted_at: ~N[2018-05-08 13:18:04.733672], owner_app: "admin_api", token: "_PXmVfh6jZjZM57bvZ_O339He1VWP-D9r4cgJjrKpPE", updated_at: ~N[2018-05-08 13:18:04.733683], user: #Ecto.Association.NotLoaded<association :user is not loaded>, user_uuid: "35ef600a-8ea2-41ad-a793-e59a5d20afcc", uuid: "e09068c2-444c-4483-8889-51c4930a0103"})
    apps/ewallet/priv/repo/report_minimum.exs:86: (file)
    (elixir) lib/code.ex:629: Code.load_file/2
    apps/ewallet/priv/repo/seeder.exs:160: EWallet.Seeder.call/1
    (elixir) lib/code.ex:677: Code.require_file/2
    (mix) lib/mix/tasks/run.ex:136: Mix.Tasks.Run.run/5
    (mix) lib/mix/tasks/run.ex:76: Mix.Tasks.Run.run/1
    (mix) lib/mix/task.ex:314: Mix.Task.run_task/3
    (mix) lib/mix/task.ex:348: Mix.Task.run_alias/3
    (mix) lib/mix/task.ex:277: Mix.Task.run/2
    (mix) lib/mix/cli.ex:80: Mix.CLI.run_task/2

Implement Pagination via starting ID + offset

Currently Pagination is only possible via per_page / page. In order to support faster pagination and allow infinite scrolling pagination, we need to support pagination via ID.

  • page_record_id: defines after which record the wanted set of records starts.
  • per_page : defines how many records are wanted.

The attribute names are up for discussions.

Logging/Tracking of who did what on what

In order to proceed with blockchain integration, we need to finally add this feature we've been pushing to "later". With this, we'll have a log of all actions that happened in the system and we will be able to find out who did what and when.

Use fewer database connections in eWallet connection pool

Currently 3 instances of ewallet is using approximately 60 connections (20 each for each instance, 10 for ewallet, 10 for ledger):

postgres=> select datname, COUNT(datname) from pg_stat_activity GROUP BY datname;
     datname     | count
-----------------+-------
 staging_ewallet |    30
 staging_ledger  |    30
(4 rows)

This might cause problems with some setups, such as Google Cloud SQL which has very low limit by default to prevent OOM.

Transaction endpoints not serializing amount

When using the ruby-sdk I noticed that the transactions endpoints don't return the amount that was processed for a given transaction. I believe these endpoints are using this serializer (I have limited elixir exposure so don't trust me 😬) https://github.com/omisego/ewallet/blob/develop/apps/ewallet_api/lib/ewallet_api/v1/serializers/json/transaction_serializer.ex

Your environment

local rails app using omisego gem connecting to the eWallet API (omise private test env)

Expected behaviour

When calling OmiseGO::Transaction#all_for_user I expect amount to be serialized and returned in the response.

Actual behavior

amount is not serialized

Randomly Failing to retrieve a transfer after insert

Subject of the issue

Randomly Failing to retrieve a transfer after insert in:

  def insert(attrs) do
    changeset = changeset(%Transfer{}, attrs)
    opts = [on_conflict: :nothing, conflict_target: :idempotency_token]

    case Repo.insert(changeset, opts) do
      {:ok, transfer} ->
        {:ok, get_by_idempotency_token(transfer.idempotency_token)}

      changeset ->
        changeset
    end
  end

Your environment

Staging environment, using Ruby SDK or iOS SDK.

Steps to reproduce

  1. Get Ruby SDK
  2. Replace the config in env.rb with real values
  3. Run
~/src/ruby-sdk on  T305-renaming! ⌚ 16:05:55
$ rspec ./spec/omisego/wallet_spec.rb                                                                                                                                                                                            ‹ruby-2.3.3›

OmiseGO::Wallet
  .all
    retrieves the list of wallets
  .credit
    with valid params
      credits the user's wallet
    with params account_id and account_address
      credits the user's wallet (FAILED - 1)
  .debit
    with valid params
      debits the user's wallet (FAILED - 2)
    with params account_id and account_address
      debit/s the user's wallet

Failures:

  1) OmiseGO::Wallet.credit with params account_id and account_address credits the user's wallet
     Failure/Error: expect(wallets).to be_kind_of OmiseGO::List
       expected #<OmiseGO::Error:70175132363600 code: server:internal_server_error, description: Something went wrong on the server, messages: > to be a kind of OmiseGO::List
     # ./spec/omisego/wallet_spec.rb:67:in `block (5 levels) in <module:OmiseGO>'
     # /Users/thibault/.rvm/gems/ruby-2.3.3/gems/vcr-3.0.3/lib/vcr/util/variable_args_block_caller.rb:9:in `call_block'
     # /Users/thibault/.rvm/gems/ruby-2.3.3/gems/vcr-3.0.3/lib/vcr.rb:189:in `use_cassette'
     # ./spec/omisego/wallet_spec.rb:55:in `block (4 levels) in <module:OmiseGO>'

  2) OmiseGO::Wallet.debit with valid params debits the user's wallet
     Failure/Error: expect(wallets).to be_kind_of OmiseGO::List
       expected #<OmiseGO::Error:70175123941460 code: server:internal_server_error, description: Something went wrong on the server, messages: > to be a kind of OmiseGO::List
     # ./spec/omisego/wallet_spec.rb:87:in `block (5 levels) in <module:OmiseGO>'
     # /Users/thibault/.rvm/gems/ruby-2.3.3/gems/vcr-3.0.3/lib/vcr/util/variable_args_block_caller.rb:9:in `call_block'
     # /Users/thibault/.rvm/gems/ruby-2.3.3/gems/vcr-3.0.3/lib/vcr.rb:189:in `use_cassette'
     # ./spec/omisego/wallet_spec.rb:76:in `block (4 levels) in <module:OmiseGO>'

Finished in 3.04 seconds (files took 0.46432 seconds to load)
5 examples, 2 failures

Failed examples:

rspec ./spec/omisego/wallet_spec.rb:54 # OmiseGO::Wallet.credit with params account_id and account_address credits the user's wallet
rspec ./spec/omisego/wallet_spec.rb:75 # OmiseGO::Wallet.debit with valid params debits the user's wallet

Expected behavior

The response should be successful instead of 500.

Actual behavior

The server returns 500.

Research

The server crashes because nil is passed as the first argument in those functions:

  defp process_with_transfer(%Transfer{status: "pending"} = transfer, wallets, token) do
    transfer
    |> TransferGate.process()
    |> process_with_transfer(wallets, token)
  end

  defp process_with_transfer(%Transfer{status: "confirmed"} = transfer, wallets, token) do
    {:ok, transfer, wallets, token}
  end

  defp process_with_transfer(%Transfer{status: "failed"} = transfer, _wallets, _token) do
    resp = transfer.ledger_response
    {:error, transfer, resp["code"], resp["description"]}
  end

Which happens because of get_by_idempotency_token is returning nil in the following code, which is not supposed to happen becasue either a record has just been inserted or has been inserted in another process.

  def insert(attrs) do
    changeset = changeset(%Transfer{}, attrs)
    opts = [on_conflict: :nothing, conflict_target: :idempotency_token]

    case Repo.insert(changeset, opts) do
      {:ok, transfer} ->
        {:ok, get_by_idempotency_token(transfer.idempotency_token)}

      changeset ->
        changeset
    end
  end

Attempts

  • Surround with Transaction PR #219
  • Retries #222

Thoughts? I ran out of ideas except for the retries with delay to solve the fact that the DB state does not seem up to date.

Admin Login throws "no function clause matching in Base.url_decode64/2"

Issue:

After running mix seed --sample in the ewallet Docker container (docker exec -it omisego_ewallet_1 mix seed --sample) and trying to follow the instructions to login as [email protected], the login is denied and the following text is output by the ewallet Docker container:

ewallet_1  | 17:38:27.435 request_id=2kmqfgt2as9jim219g0002n1 [info] GET /admin
ewallet_1  | 17:38:27.514 request_id=2kmqfgt2as9jim219g0002n1 [info] Sent 200 in 78ms
ewallet_1  | 17:38:40.124 request_id=2kmqfhkmpvce4nsp2o0002q1 [info] POST /admin/api/login
ewallet_1  | 17:38:40.237 request_id=2kmqfhkmpvce4nsp2o0002q1 [info] Sent 500 in 113ms
ewallet_1  | 17:38:40.239 [error] #PID<0.1125.0> running UrlDispatcher.Plug terminated
ewallet_1  | Server: localhost:4000 (http)
ewallet_1  | Request: POST /admin/api/login
ewallet_1  | ** (exit) an exception was raised:
ewallet_1  |     ** (FunctionClauseError) no function clause matching in Base.url_decode64/2
ewallet_1  |         (elixir) lib/base.ex:482: Base.url_decode64(nil, [padding: false])
ewallet_1  |         (salty) lib/salty/utils.ex:18: Salty.Utils.decode_key/2
ewallet_1  |         (salty) lib/salty/secret_box.ex:53: Salty.SecretBox.decrypt/1
ewallet_1  |         (cloak) lib/cloak.ex:170: anonymous fn/3 in Cloak.decrypt/1
ewallet_1  |         (elixir) lib/enum.ex:1899: Enum."-reduce/3-lists^foldl/2-0-"/3
ewallet_1  |         (cloak) lib/cloak.ex:164: Cloak.decrypt/1
ewallet_1  |         (cloak) lib/cloak/types/encrypted_map_field.ex:26: Cloak.EncryptedMapField.load/1
ewallet_1  |         (ecto) lib/ecto/type.ex:647: Ecto.Type.process_loaders/3

Compose File:

version: '2.1'
services:
  ewallet:
    image: omisego/ewallet:latest
    depends_on:
      db:
        condition: service_healthy
    environment:
    - DATABASE_URL=postgresql://postgres:password@db:5432/ewallet
    - LOCAL_LEDGER_DATABASE_URL=postgresql://postgres:password@db:5432/local_ledger
    ports:    
    - 4000:4000
    
  db:
    image: postgres
    restart: always
    environment:
      POSTGRES_PASSWORD: password
    ports:
    - 5432:5432
    volumes:
    - ./postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 30s
      timeout: 30s
      retries: 3

Commands:

$ docker-compose up
$ docker exec omisego_ewallet_1 mix do local.rebar --force, local.hex --force, ecto.create, ecto.migrate
$ docker exec -it omisego_ewallet_1 mix seed --sample

Allow the eWallet to work without integration

Currently, the eWallet cannot be used as a stand-alone with only mobile applications using it (currently, it is needed for a provider to create an application to store users, etc.)

This feature is needed for the sample Coffee shop application we're going to be working on.

It involves:

  • A merchant app, where an administrator can login (by entering email/password). From this application, a logged-in admin can then proceed to top-up or purchase on behalf of a user by scanning a user's identity QR code. This application should automatically logout admins unless they specified a "Remember Me" button, hence the need to add Face ID / Touch ID.
  • A user app, where a user should be able to sign up and login (all through the eWallet API, /signup is currently missing. The user can then see his balances or generate his identity QR code.

Tasks:

  • Ensure the differentiation field between admins and users is only provider_user_id
  • Add /user.signup endpoint in client API, which will only proceed a request if ALLOW_USER_REGISTRATION is set to true (defaults to false)
  • Add /user.login endpoint in client API (which follows the same rules as above, depending on ALLOW_USER_REGISTRATION

Implement advanced filtering for Admin API

Currently, it isn't possible to do proper advanced filtering using search_term and search_terms. An advanced filtering system needs to be implemented (potentially using a new field, filters?) that would contain a list of AND/OR predicates.

The filtering system should allow association filtering up to one level (e.g. from /wallet.all, I should be able to specify account.name = something. Different comparison mechanism should be supported: greater, equal, etc.).

Open to suggestions for Elixir libraries that could handle this.

Cannot get ewallet to setup on Ubuntu (any version) using Docker

Subject of the issue

Cannot get ewallet to setup correctly on Ubuntu using Docker or git clone.
Describe your issue here.

git clone https://github.com/omisego/ewallet && cd ./ewallet
$ mix deps.get

The above instructions are not working. I get an error stating * (Mix) The task "archive.check" could not be found.

Also when using the docker image, i keep getting the below error:
23:32:07.935 [error] Postgrex.Protocol (#PID<0.778.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (127.0.0.1:5432): connection refused - :econnrefused

I CAN connect to that port on my local so i don't know why i'm getting the issue.

Your environment

Ubuntu 17

Provide API docs in JSON format

This issue is a simple task to get started with the eWallet SDK. It's available for anyone from the community to work on - don't be shy!

Subject of the issue

Currently, the API docs are available in Swagger format and in YAML. We'd like them to be available in JSON as well under /api/docs.json for client to potentially generate SDK code dynamically.

Add reset frequency to cached balance

Currently, cached balances are either calculated from scratch (strategy since_beginning) or from the last caching point (strategy since_last_cached).

The since_last_cached strategy should feature an additional option (reset_frequency) to allow a provider to specify a once in a while reset of the cache. Basically, every X times (as specified in reset_frequency, the since_last_cached strategy will switch to a since_beginning strategy.

This feature prevents an invalid cached balance from running rampant forever, since it will be reset and re-calculated from scratch. Note that incorrect balances should not happen, but this measure will ensure that if it does happen once, the problem will solve itself and give us time to figure out the problem without breaking the whole system.

Dockerhub images: missing Hex and Rebar

Dockerhub

There seems to be a typo on Dockerhub which causes a syntax error.
docker exec <container-id> mix ecto.create, ecto.migrate should be docker exec <container-id> mix do ecto.create, ecto.migrate.

Also the current latest image doesn't seem to properly install mix local.hex and mix local.rebar. Since I get the following error:

docker exec d5967cfb5a10 mix do ecto.create, ecto.migrate
Could not find Hex, which is needed to build dependency :credo
Shall I install Hex? (if running non-interactively, use "mix local.hex --force") [Yn] ** (Mix) Could not find an SCM for dependency :credo from EWallet.Umbrella.Mixfile

Environment

  • OS: mac osx 10.12
  • Docker: 18.03
  • Docker-compose: 1.20

Steps to reproduce

I used the following docker-compose.yml with docker-compose up and after that ran docker exec <container-id> mix do ecto.create, ecto.migrate in a seperate window.

version: '3.1'
services:
  db:
    image: postgres
  omisego:
    image: omisego/ewallet:latest
    ports:
      - 4000:4000
    environment:
      DATABASE_URL: "postgresql://postgres@db:5432/ewallet"
      LOCAL_LEDGER_DATABASE_URL: "postgresql://postgres@db:5432/local_ledger"
    links:
      - db

Expected behavior

I expected the Dockerfile in omisego/ewallet:latest to properly install local.hex and local.rebar.

Actual behavior

$ docker exec d5967cfb5a10 mix do ecto.create, ecto.migrate

Could not find Hex, which is needed to build dependency :credo
Shall I install Hex? (if running non-interactively, use "mix local.hex --force") [Yn] ** (Mix) Could not find an SCM for dependency :credo from EWallet.Umbrella.Mixfile

Design issues in Admin Panel

  • Total supply shows 0 after minting a token on creation
  • When accessing a wallet detail, the "Wallet" section is not highlighted anymore in the menu. Same problem for accounts.
  • Show primary/burn/secondary in wallets list when making a transaction (even just an icon, number 1, number 2 or a fire icon)
  • Can't see all the wallets when creating a transaction request, but can when consuming? Should use /account.get_wallets with owned = false.
  • Add copy button for API keys / addresses / ...

Drop libsodium in favor for alternatives

Currently we're using libsodium for metadata encryption in the eWallet DB and Local Ledger DB. Unfortunately, as libsodium (via enacl) is a NIF and I couldn't find a way to bundle libsodium along with release, this makes distributing eWallet binaries for supported platforms a bit harder than I'd hope (e.g. no cross compilation, for one thing).

As libsodium is only used for metadata encryption via Cloak (hopefully not very important) it might more more feasible to switch to AES256-GCM instead. I'd love to hear what you think @thibault @unnawut. Also looping in @fred.

/minted_token.all not returning any minted tokens

Subject of the issue

Can't retrieve the full list of tokens.

Your environment

I am on a fresh Vagrant install, prepared using the goban repo.

Steps to reproduce

  • Create a fresh environment (I used mix seed --sample) and launch the server
  • Create a new token using /minted-token.create
  • Save the token ID
  • Call /minted_token.get on that token ID -> the token data is displayed
  • Call /minted-token.all -> no data

This is the full JSON response I get from .all endpoint :

{
  "version": "1",
  "success": true,
  "data": {
    "pagination": {
      "per_page": 10,
      "is_last_page": true,
      "is_first_page": true,
      "current_page": 1
    },
    "object": "list",
    "data": []
  }
}

And this is the response I got from .get endpoint :

{
  "version": "1",
  "success": true,
  "data": {
    "updated_at": "2018-02-28T23:10:13.527129Z",
    "symbol": "SIMSIM",
    "subunit_to_unit": 100,
    "object": "minted_token",
    "name": "Simcoinzzz",
    "id": "SIMSIM:330acf3a-f46a-4dd8-b642-4c246d02da26",
    "created_at": "2018-02-28T23:10:13.527117Z"
  }
}

All tests have been done through Swagger only.

Expected behavior

The token list should not be empty.

Actual behavior

No token is available in that list.

Link to API error codes

Subject of the issue

The list of API error codes is on Google Drive and seems to be access-protected.

Steps to reproduce

Access the "eWallet Error Codes" link from this page (in incognito mode for instance)
https://ewallet.demo.omisego.io/api/swagger#/

Expected behavior

See the doc

Actual behavior

Authorization prompt from Google Drive

Do not run Erlang VM as PID 1

Subject of the issue

Running non-Init process as PID 1 is a Bad Idea ™.

Your environment

Docker image generated from Dockerfile

Steps to reproduce

  1. Build docker image (docker build)
  2. Run it.

Expected behavior

Lightweight init being ran as PID 1, such as Tini, or S6.

Actual behavior

Erlang VM is running as PID 1.

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.