GithubHelp home page GithubHelp logo

hubiinetwork / nahmii-sdk Goto Github PK

View Code? Open in Web Editor NEW
8.0 8.0 0.0 4.23 MB

Javascript SDK for using the hubii nahmii APIs

Home Page: http://hubii.com

License: GNU Lesser General Public License v3.0

JavaScript 100.00%
javascript nodejs sdk sdk-js nahmii trading payments ethereum dex

nahmii-sdk's Introduction

NAHMII SDK

About the SDK

This is a javascript library that wraps the nahmii APIs making them easier to get started with.

About nahmii

nahmii is both the name of the company as well as of the scaling solution for the Ethereum blockchain. It is a hybrid centralized/decentralized solution that enables instant (micro-)payments, trading and trustless settlements. See www.nahmii.io for additional information.

About hubii

hubii is no more. It is the old name of the company. If you find references to it, think nahmii. Still this repository is hosted in the GitHub organization archaically labelled hubiinetwork.

Prerequisites

  • To use this software you need a modern version of NodeJS and NPM. We recommend having the versions 10 installed and updating NPM to the latest available version.
  • You will also need an API key for access to the nahmii APIs.

Installation

To install the SDK into your project, simply run:

npm install nahmii-sdk

Dependency management

After you have installed the nahmii-sdk module into your own project, please make sure to install the dependencies listed as peer dependencies into your project to have it included in the end product.

The reason this SDK uses peer dependencies is that it is actively doing type checking for some shared types in some situations. To have type checking work in a nodejs environment, all npm-based types must be de-duplicated.

To force a de-duplication after you have installed several modules, just run the following command:

npm ddp

In most cases this should not be needed though.

Usage

Create a provider to gain access to the low-level SDK:

    const nahmii = require('nahmii-sdk');

    const provider = await nahmii.NahmiiProvider.from(nahmii_domain, nahmii_app_id, nahmii_app_secret);

The provider can be used to gain access to the API resources, such as a wallet's balance:

    const nahmii = require('nahmii-sdk');
    const provider = await nahmii.NahmiiProvider.from(nahmii_domain, nahmii_app_id, nahmii_app_secret);

    // Logs all assets of the specified wallet to the console
    const balances = await provider.getNahmiiBalances(wallet_address);
    console.log(balances);

To make a more advanced workflow as easy as possible there is also a higher level SDK, e.g.: the Wallet class and the Payment class. In this example we create a payment, sign it and register it with the API:

    const nahmii = require('nahmii-sdk');
    const provider = await nahmii.NahmiiProvider.from(nahmii_domain, nahmii_app_id, nahmii_app_secret);
    const wallet = new nahmii.Wallet(private_key, provider);

    // Creates a new Payment, providing essential inputs such as the amount,
    // the currency, the sender, and the recipient.
    const monetaryAmount = nahmii.MonetaryAmount.from(amount, erc20_token_address);
    const payment = new nahmii.Payment(wallet, monetaryAmount, wallet_address, recipient_address);

    // Signs the payment with the wallet passed during instantiation
    payment.sign();

    // Sends the signed payment to the API for registration and execution and
    // logs the API response to the console.
    payment.register().then(console.log);

Reference manual

Fundamentals

Workflow: Payments

Workflow: Settlement

Base Layer

Utilities

Contributing

To contribute to the development of the nahmii SDK, you need to clone the repository https://github.com/hubiinetwork/nahmii-sdk.git.

You changes should be made on a branch starting with the name "feature/" (e.g.: feature/awesomesauce) and be branched from the latest "master" branch.

We also follow a few practices that we expect contributors to also adhere to.

Practices

Branching Model

The master branch is expected to always be in a green state. Every commit to master is expected generate a new NPM release of the library. For more long lasting work, create a feature branch and merge it through a pull request.

Pull Request

Don't just push a new branch and expect us to magically discover it and do something with it; also make sure you create a pull request for your branch where the changes can be examined and findings recorded in a organized manner.

If your changes address either partially, or fully, an open issue in the backlog, make sure to reference it in the description of your pull requests.

Also make sure to reference one or more of the admins of the repo and set them as reviewers for your pull request.

Code Review

As part of the pull requests all reviewers should as soon as possible provide constructive feedback on the pull request.

The reviewer should look at the following as a minimum:

  • Code quality, readability, maintainability, performance, security
  • Test code quality, coverage, readability, maintainability
  • Design of any public APIs, including documentation
  • Overall architecture of solution, does it fit with current designs
  • Missed opportunities: simplification of design, refactoring, invalidation of previous assumptions

Test Driven Development (TDD)

Why? Because done right, the codebase becomes better and getting full test coverage becomes trivial. Always start by writing a test that turns red, then change your production code to turn it (and all other tests) green again. Then do some refactoring as needed. Refactoring is arguably the most important step, so dont skip it. Rinse and repeat. Follow the cycle "red-green-refactor" and don't leave any of the steps out. And yes, an experienced TDD practitioner can in most cases easily spot code that has not been created using TDD.

There is no need to limit you test suite to only have unit tests, but the unit tests themselves should have ~100% code coverage.

Who do I talk to?

nahmii-sdk's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nahmii-sdk's Issues

Fix docs: nahmiiProvider.getTransactionConfirmation()

nahmiiProvider.getTransactionConfirmation() โ‡’ Promise
should be consistect with:

/**
* Waits for a transaction to be mined, polling every second.
* Rejects if a transaction is mined, but fails to execute, for example in an out of gas scenario.
* @see https://docs.ethers.io/ethers.js/html/api-providers.html#transaction-receipts
* @param {string} transactionHash
* @param {number} [timeout=60] - Seconds to wait before timing out
* @returns {Promise}
* @example
* const transactionHash = await wallet.depositEth('1.1', {gasLimit: 200000});
* const transactionReceipt = await getTransactionConfirmation(transactionHash);
*/

Incorrect error logged

There is an error logged (LOG_LEVEL=debug) when the NahmiiEventProvider is shutting down. It seems its not unsubscribing from all socket.io events before it closes the connection.

Consistent hash function

The SDK seems to have a different hash function from the one expected in the smart contracts. The SDK hash an array of arguments, while the smart contract requires the hashing to be done in another way (hash of hash), please see:
https://github.com/hubiinetwork/striim-contracts/blob/develop/test/mocks.js#L419

Therefore, the signature generated by the SDK failed to pass the genuine checks in the startChallengeFromPayment function on the smart contract.

Also, the signature needs to be in the following format:

"signature": {
       "v": {"_bn": "1c"},
       "r": "0x23...",
       "s": "0x23..."
}

The r and s properties need to be prefixed with 0x, otherwise it can't go through the ethers lib's contract object's input validator when calling the functions that accept the payment receipt as an argument.

Add Ethereum sign function

Description

The SDK should be able to create Ethereum signatures (https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign). These prefixed signatures are the ones from which smart contracts is able to recover the address of the signee.

A function along the following prototype could be implemented in lib/utils.js. (The prototype assumes this file location.)

/**
 * Signs the specified message the Ethereum way according to {@link https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign|eth_sign}
 * @param message
 * @param privateKey
 * @returns {string} Signature as a hexadecimal string.
 */
function ethereumSign(message, privateKey) {
        const prefixedHash = new Buffer(
            strip0x(hash('\x19Ethereum Signed Message:\n32', message)), 'hex'
        );
        const signature = ethutil.ecsign(prefixedHash, new Buffer(strip0x(privateKey), 'hex'));
        return `0x${signature.v.toString(16)}${signature.r.toString('hex')}${signature.s.toString('hex')}`;
}

This prototype was derived from Ethereum specific signing logics in striim-contracts' mocks module.

Definition of done

  • Ethereum specific signing has been implemented
  • Unit tests are updated

Details & Questions

Depends on

Requests using a token generated by the identity server often fail with code 503

The requests fail for a few minutes, seem OK for ~15 seconds, then go back to failing

503 response request and response headers:
screenshot from 2018-10-01 13-26-46

Notice that almost immediately after this, with the exact same token, the requests start to return 200
screenshot from 2018-10-01 13-27-05

A short time later, the requests go back to failing.

The response doesn't seem to give any clues as to why it's failing, only a generic 503 page:

<html>
<head><title>503 Service Temporarily Unavailable</title></head>
<body bgcolor="white">
<center><h1>503 Service Temporarily Unavailable</h1></center>
<hr><center>nginx</center>
</body>
</html>
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->

Allow semantic payment sender reference

Is your feature request related to a problem? Please describe.
The solution to this enhancement is a prerequisite to an issue related to the airdriip-payment-cli.
As a service making unique payments (airdriip-payment-cli)
I would like to seed the Payment.sender.reference with semantic information
In order to detect and prevent multiple payments to the same wallet.

Describe the solution you'd like
As a service generating new Payment objects
I would like to accept a new optional argument accepting the uuid used as Provider.senderRef
In order to permit clients to seed the uiid with semantic information.
A random uuid is assigned if no uuid is given as argument.

Describe alternatives you've considered
As a stateless payment generating client
I have to compare payments by values (amount, timestamp)
In order to infer if my payment is payed in a previous process or should be payed in the current process.
This is a roundabout heuristic way to compare candidate payements with receipts.

Additional context
Payments are currently always unique, regardless of content or intention, since the Payment.senderRef is a random field generated during construction.

Refactor and support v1.0-ropsten.8

Refactor based on the data structure changes in https://github.com/hubiinetwork/nahmii-contracts/releases/tag/v1.0-ropsten.6

  • Support Null Settlement
  • Refactor getCurrentPaymentChallenge into different functions for checking the challenge statuses. These functions will wrap the contract functions of proposalNonce, proposalExpirationTime, hasProposalExpired, proposalStageAmount, proposalStatus
  • Refactor depositTokens to use receiveTokens which has an added argument balanceType
  • Update abis

Superagent in browsers

Superagent has slightly different API in browser vs node. Setting the "agent" for a request (to use for keep-alive connections) is not supported in the browser version and generates a warning in the console.

Need to be able to retrieve a wallet's settled & staged balances

Currently a wallet's 'available' balance (balance that can be used off-chain) can be retrieved with provider.getNahmiiBalances(wallet_address) or wallet.getNahmiiBalance().

We can get deposited, settled, staged balances directly from the SC (likely, pending confirmation from Jensivar)

The SDK's balance API should look something like

  • getAvailableBalance()
  • getStagedBalance()
  • getSettledBalance()
  • getDepositedBalance()

Along with this change, should

  • add a convenience function should be added to utils, allowing summation of balance objects.
    eg
utils.sumBalances(staged_balance, settled_balance, avaialable_balance, some_other_balance, ...)
  • wrap the Wallet API GET ethereum/wallets/{address}/balances with a similar function to the others that returns an account's on-chain balance.
  • write some documentation explaining how different types of balances work

Annoying console logs

Currently, this lib logs to the console as it runs without an apparent way to disable it.

I suggest that when things appear to be running as expected, logs aren't shown. In unusual circumstances like an error, I think it's fine to show a log.

Please advise @morfj

When wallet has a nahmii balance in a currency not in the supported tokens list, getNahmiiBalances crashes

When a wallet has a nahmii balance in a currency that is not in the list of supported tokens, the getNahmiiBalance function will throw the error below:

TypeError: Cannot read property 'symbol' of undefined
    at Wallet.getNahmiiBalance (/usr/local/lib/node_modules/nahmii-cli/node_modules/nahmii-sdk/lib/wallet/wallet.js:85:36)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)
Error: Unable to retrieve the balance.
    at Object.handler (/usr/local/lib/node_modules/nahmii-cli/src/commands/show-commands/balance.js:21:19)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)

Enhance the message for minimum balance errors

The backend API can response the reason of this error in the format:

{"message":"Insufficient funds: The minimum balance of this token is 0.01.","stack":"..."}

But the SDK only says Insufficient funds!

throw new Error('Insufficient funds!');

The downstream clients, such as the hubii-core, need to know the requirement for the minimum balance in order to show a detailed error message. Also, the front end clients need to localize the message, so it'd better provide a way for the clients to know the type of error and the required minimum balance.

Here is a suggestion:

  1. Create a new error class called InsufficientFundError that extends the Error class. This error adds a new field called minimumBalance.

  2. Parse the 0.01 from the message field of the API error response, and save it to the minimumBalance of a InsufficientFundError instance. (It would be better and safer if the API can return an additional field for the minimum balance, so the SDK won't need to do the parsing.)

Fix concurrent settlement operations

When settling or staging more than one settlement challenges in parallel for a wallet/currency pair, it will introduce race condition on ethereum nodes, resulting in transaction failures.

The solution to this is to ensure the transactions in the startChallenge or settle function of the Settlement class are executed in the sequence of transaction confirmations.

utils.isSignedBy doesn't seem to be recognising a valid signature

Came across this issue when trying to use the airdriip-service, which uses the SDK's isSignedBy function.

Payload sent to the airdriip service:

{
  "document": "I agree to the nahmii airdriip T&C and wish to register my address",
  "sender": "0x910c4BA923B2243dc13e00A066eEfb8ffd905EB0",
  "seal": {
    "hash": "0x01d2d0f6d4d8584977c45f770815d1db3c67475c28419838549ce7c4626b44c1",
    "signature": {
      "v": 27,
      "r": "0xd22cd2712c47c404d436e0e6075ffe4d617f457261ba02386bb132a999a6d467",
      "s": "0x111410a4e46fd825a5a686b20dd385811932e6956e3684baf13ba94d4cc31069"
    }
  }
}

Response:
422: Signature is not matching.


Converting the signature into RPC format, we can verify it's correct:

import { toRpcSig, toBuffer } from 'ethereumjs-util';

const sig = {
  v: 27,
  r: "0xd22cd2712c47c404d436e0e6075ffe4d617f457261ba02386bb132a999a6d467",
  s: "0x111410a4e46fd825a5a686b20dd385811932e6956e3684baf13ba94d4cc31069"
}
const rpcSig = toRpcSig(sig.v, toBuffer(sig.r), toBuffer(sig.s));
console.log(rpcSig);

0x0946d84a81606a20271f5a7ce8f3e9156e8c9b2e5eed56954fb3a2a6632f5022388eb4ba2dbf3ff0bfb46ad40efbe42f93feee242ae2e55a016d1fcc770deddd01

Etherscan verifying the signature is valid: https://etherscan.io/verifySig/1380
ethers.js (v4.0.0 or greater required) verifying the signature is valid:

const ethers = require('ethers');

const signature = '0x0946d84a81606a20271f5a7ce8f3e9156e8c9b2e5eed56954fb3a2a6632f5022388eb4ba2dbf3ff0bfb46ad40efbe42f93feee242ae2e55a016d1fcc770deddd01';
const message = '0x9daff1073bc37bd6d0261e48bda49f3ba1bbbd71838a34602acb06407aa5ea47';

console.log(ethers.utils.verifyMessage(message, signature));

0x910c4BA923B2243dc13e00A066eEfb8ffd905EB0


I've tested this using

  • the ethers.js Wallet.prototype.signMessage function
  • the Ledger Nano S eth.signPersonalMessage function
  • the Trezor Session.signEthMessage function

and had the same results

Consider using the hubii eslint config, or a variation of it

Having a defined set of code style standards will become more important the contributors count increases.

@jonbern had the initiative to create a company-wide config some months ago, I think it would be beneficial to put it into action in this repo https://github.com/hubiinetwork/eslint-config

As well as making it easy to enforce code quality standards, defining an eslint config can increase development efficiency in a lot of editors that automatically do things like indentation, string definition rules, spacing rules, etc for you (srsly, who wants to spend their time doing that stuff... ๐Ÿ˜„)

Hardware wallet support

Current implementation only supports specifying a private key, and that is not compatible with using hardware wallets where the private key never leaves the device. Enhance the Wallet class to support using a async callback for signing actions.

Probable new Wallet#constructor() signature: constructor(provider, (private_key|address) [, signature_provider])

If you don't have the private key, instantiate the Wallet with the address and a signatureProvider function instead.

Payments, Receipts and other classes will support using a Wallet as a signature provider, making the privatekey to sign() functions optional, e.g.: sign([private_key]). An argument can be made for removing the private key altogether from the sign function and simply expect the consumer has provided a wallet instance for the private key instead. Opinions?

Tasks

  • Update Wallet and create a sign function.
  • Update Wallet with new constructor
  • Update Wallet#depositEth()
  • Update Wallet#depositToken()
  • Update Payment#sign()
  • Update Receipt#sign()

Removal of NahmiiContract constructor warnings

The current warning of use of constructor of NahmiiContract when not called from its function from() should be removed. The entire shift to using from() should be done in entirety for all descendants of NahmiiContract within this repository and is hence deferred to later issue.

Deposit functionality

The current deposit functionality needs some work before it's ready for complex applications. Below are my proposed changes & additions to the deposit API

Deposit

3 deposit methods for Wallet, each of which returns a tx hash as soon as they're broadcast

  • .depositEth(currency, amount, options)
  • .initiateTokenDeposit(currency, amount, options)
  • .completeTokenDeposit(txId, options)

The options param would allow the user to customize things like gas price / gas limit

Get pending deposits

  • A method is required to get a wallet's pending deposits. This will be called once when the wallet is loaded, and is required to keep state up to date if the user does something like close the app or lose connection half way through a deposit
    A pending deposit would need have a type eth or token. the token type could be
  • initiated and unconfirmed (approve tx unconfirmed)
  • initiated and confirmed (approve tx mined)
  • completing (deposit tx mined)
    Rough example of what the .getPendingDeposits() return value could look like:
[
  {
     type: "eth",
     amount: "..."
     txId: "..."
     timeBroadcast: "..."
  },
  {
     type: "token",
     stage: "initiated",
     confirmed: bool,
     currency: "...",
     amount: "...",
     txId: "...",
     timeBroadcast: "..."
  },
  {
     type: "token",
     stage: "completing",
     currency: "...",
     amount: "...",
     txId: "...",
     timeBroadcast: "..."
  }
]

Deposit event API

  • We need an event API to notify the front-end when a deposit has changed status. The event API would need to be aware of deposits that were initiated outside of the SDK. The message passed with an event would be similar to that of an object returned part of the .getPendingDeposits() method

Payment.from() and Receipt.from() breaking change due to requiring wallet instance

Previously it was possible to instantiate a Payment object without a real provider or a wallet instance through the from() function:

const payment = sdk.Payment.from(json);
return payment.isSigned();

Now this is not possible anymore, and I need to pass a Wallet instance to the from() function. This breaks functionality in Trading AP that is used to check whether Payments and Receipts are signed.

To get around this, I have to write this sort of hacky code:

const config = require('./config');

const dummyProvider = {
  network: {
    chainId: '3'
  },
  resolveName: () => Promise.resolve('Ropsten'),
  operatorAddress: config.ethereum.contractOwner
};

// A random private key (Trading API doesn't sign anything, it just needs to check if something already has been signed)
const dummyPrivateKey = '0x010f3fa2b24726878516342f463f3ff36105ad51325201179deafdc38357a319';

const dummyWallet = new sdk.Wallet(dummyPrivateKey, dummyProvider);

const payment = sdk.Payment.from(dummyWallet, json);
return payment.isSigned();

I think it's an unintentional consequence that Wallet now has become required in order to check the signature.

Remove NestedError impl

nahmii-sdk is currently using it's private version of NestedError.
That is not neccesary any more since NestedError is now available as part of the omphalos-error-utils.

Remove the private NestedError implementation and get it from omphalos-error-utils.

Request hangs

When an request is issued to the Nahmii back-end,
it happens that the request hangs.

The internal feature NahmiiRequest is using super agent requests. The requests are made without timeout option.

Propose to add a timeout argument to the constructor of the NahmiRequests class.

Unhandled promise rejection fetching API access token

It appears on ln 96 in nahmii-provider.js, Promise.reject is thrown and not caught anywhere within the SDK.

The function throwing Promise.reject is initiated from a call to the NahmiiProvider.getApiAccessToken method.

When this method is called manually by the user, the error can be caught by wrapping the call in a try catch statement, which is fine.

The issue I'm experiencing is that on initialization, NahmiiProvider instances are set to automatically call this method every minute. If there's a network error, the error will be thrown and I can't find a way to handle it.

Not sure if there's an obvious way to catch this that I'm missing, but until I do find a solution it'll be an issue in the hubii core project which is currently configured to loudly complain if there're any unhandled errors.

A simple fix is just to return the error instead of throwing via Promise.reject, but not sure if that's the cleanest solution, or if there's a way to catch this outside of the SDK.

Any input would be appreciated @morfj

Thanks

Silent failure-and-continue

Swallowing error such as these can potentially lead to a disaster by allowing the function to keep running without handling the error. As a minimum the error should be debug logged. If its actually NOT an error, then the design should be reconsidered as it is using errors for something it shouldnt.

} catch (error) {} //eslint-disable-line

Inherited ethers methods require a .address property

Methods like getBalance, getTransactionCount etc are broken until this is fixed.

#55 will add tests and re-add the address property to ensure inherited ethers methods are covered helping prevent issues like this occurring again

Contract instance validation with NahmiiContract#from()

Currently nahmii contract instances descending from NahmiiContracts are instantiated with a constructor that calls super('SomeContractName', walletOrProvider). Rather they should be instantiated by use of NahmiiContract#from(contractName, walletOrProvider).

Once all descendants of NahmiiContract in this repo have been updated accordingly the deprecation warning in the constructor of NahmiiContract may be reintroduced.

number is not a suitable data type to represent amounts

I noticed that some functions in the SDK accept the parameter amount as a number.

JS does funky stuff with numbers that contain 7 or more decimal places.

For example, with 6 decimal places everything is fine

const x = 0.000001; // 6 decimal places
console.log(x); // 0.000001

Adding 1 more 0, the number may be represented in exponential notation, which can blow up

const x = 1.0000001; // 7 decimal places
console.log(x); // 1.0000001

const y = 0.0000001; // 7 decimal places
console.log(y); // 1e-7

ethers.parseEther(x); // runs sucesfully
ethers.parseEther(y); // blows up

There are also many more nasty bugs that could slip by due to the nature of floating point precision in JS. These kinds of bug don't result in an exception, and are often undetected until it's too late (which in nahmii's case means money lost). Due to the micropayment nature of nahmii, it's doubly important that we consider this. Here's a quick article on JS floating point precision https://hackernoon.com/a-note-on-numbers-in-ethereum-and-javascript-3e6ac3b2fad9

Numbers in JS are weird.
Allowing users to use numbers in place of strings is tempting fate, especially when considering a lot of developers using this SDK may be coming from other, louder failing languages.

I suggest that it's made a rule to never to allow amounts to be represented as a number, instead always using a string or BN. Please let me know your thoughts, @morfj

Amount as number (Wallet)

Amount must always be represented as string or BigNumber, never as Number.

The Wallet class allows input amount to be represented as number a few places.
Those should be restricted to only allow BigNumber or string.

  • depositEth(amountEth, options)
  • approveTokenDeposit(amount, symbol, options)
  • completeTokenDeposit(amount, symbol, options)

Set log level on ethers

Third-party lib ethers has default log level of info, chosen from the set of ['debug', 'info', 'warn', 'error', 'off'].

The default log level displays warnings when discovering smart contracts with overloaded functions. It is thus desirable to be able to adjust the log level of ethers so that one may prevent warnings in the mentioned case as well as in other scenarios.

This issue describes the enablement of toggling the ethers log level.

Add options to NahmiiProvider

When creating a NahmiiProvider
I would like to give it some options
in order to control how the underlying transport layer is working.

Currently we only want to control the timeout parameter of
superagnent. We could require only the timeout parameter in the constructor but it is probably useful to send the options wrapped in an object so that options can be added in the future.

This feaure will also affect the internal object NahmiiRequest,

Support settlement/withdraw

New APIs

Based on the settlement experiments in https://github.com/hubiinetwork/nahmii-demo, the overall workflow to withdraw a certain amount of balance from the nahmii smart contract could be as follow:

  1. Check if the wallet's condition is permitted to start new settlement.
  2. Start new settlement challenge period.
  3. Shift the settlement balance to staged balance.
  4. Withdraw to the on-chain wallet address.
  5. Allows to convert an amount of staged balance back to unstaged balance(deposited balance), so it is available to use within nahmii again.
  6. Be able to display staged balance that is withdraw-able without settlement.

Accordingly, below is a draft proposal for the SDK to create settlement and withdraw related API by encapsulating the corresponding contracts' functions:

  1. driipSettlementChallenge.getPhase(walletAddress), for querying the current challenge phase for a wallet. It will be used to decide whether it allows to start new challenge or if a challenge is ended so as to call the exchange.settleDriipAsPayment
  2. driipSettlementChallenge.startChallengeFromPayment(receiptJSON, walletAddress, stageAmount). The stageAmount is the amount to be made withdraw-able after the settlement succeeded.
  3. exchange.settleDriipAsPayment(receiptJSON, receiptJSON.sender.wallet). After the challenge period is ended, it needs to call this function to shift the settled balance to the staged balance, which is the total withdraw-able amount. The receiptJSON can be determined by the nonce fetched from driipSettlementChallenge.getChallengeNonce(walletAddress). The SDK would only need to expose an API function such as settlePayment(walletAddress), as it can encapsulate the logic to decide which receipt to use for settlement.
  4. clientFund.withdraw(withdrawAmount, currency, currencyId, ''). Call this function to withdraw a certain amount of staged balance.
  5. clientFund.unstage(stagedAmountAfterWithdraw, currency, currencyId). Allow the client to shift back some amount of staged balance back to unstaged balance.
  6. clientFund.stagedBalance(walletAddress, currency, currencyId).

The functions that will sign transactions are in the steps 2, 3, 4. The ethers lib supports signing the transactions in a convenient way using its Contract class for software wallets. However, it doesn't support signing for hardware wallet natively, so we will need to a way to generate the corresponding transactions for these functions for the hardware wallets to sign.

One way is to hook with the sign callback argument in the constructor of the Contract class. For example, the hubii core leverages the ethers lib's Contract sign callback to automatically generate the transaction object, which contains both the encoded data property and a nonce. See https://github.com/hubiinetwork/hubii-core/blob/97b85b35a83258ae0f25dbc7b442016b12b5cda8/src/containers/WalletHoc/saga.js#L194

Events

The information returned from getPhase is not enough to determine whether it is at the right stage to start new challenge or settle driip payment functions. The transaction could be failed to be confirmed in the network due to exceptions caught in the smart contract, and the front end needs to know the status of the transaction they sent.

Therefore, it would be better to use event logs to determine when to call what functions during settlement process. Also the transaction history should include the logs for the failed transactions, such as failed to startChallengeFromPayment, so the clients can figure out what is going wrong instead of wasting gas in repeatly trying to call the function.

Ideally, the backend could listen, parse and index the events involved in the above actions, so make it easier for the front ends to query the transaction history.

  • StartChallengeFromPaymentEvent(payment, wallet)
  • SettleDriipAsPaymentEvent(payment, wallet, challengeStatus)
  • WithdrawEvent(msg.sender, amount, currencyCt, currencyId, standard)

This is just a draft, so please feel free to comment.

Many thanks.

Crash in NahmiiProvider

When NahmiiRequest gets an http error
then that error is returned and processed by the NahmiiProvider.

When the NahmiiProvider processes the errors
then the NahmiiProvider itself happens to crash
while attempting to capture the error message of the error.

Fix the NahmiiProvider so that all errors from NahmiiRequest is handled gracefully.

Validate contract addresses from ABIs against cluster information

All contracts should be validated against the run-time cluster information to ensure actions happen on the same contracts that the cluster is operating on.
Potentially allow a flag to disable this check in case you want to forcefully run a command against a an older contract?

Undocumented public method

async getNahmiiStagedBalance(ct) {

This method should be documented like the other methods. Does it really belong in the Wallet class though? Does it require a signature for anything? Maybe better located in the provider or a dedicated "BalanceTracker" class?

Refactor settlement classes

https://drive.google.com/file/d/13ZoP-qH3FJ70BDXBMolJXBVq2wsaIQu5/view?usp=sharing

Copy of Refactor settlement classes

I am planning to refactor the settlement classes. Above is a class diagram to illustrate how we could refactor and improve the settlement related classes. Below are some notes behind it:

  1. The state-fetch APIs are consolidated into the state classes from the current implementation, so it can still poll the states using a provider without a wallet object.

  2. SettlementStates will be responsible for encapsulating the states in different challenge types.

  3. Challenge will be responsible for executable actions, abstract away from the different challenge types.

  4. In most cases, the developers would only need to use SettlementStates to get the states of the challenges and use Challenge to start or settle a challenge. Also, they don't need to be aware of the different types of challenges.

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.