Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CIP-0030] Adding getCollateral function to the connector API #208

Merged
merged 6 commits into from
Apr 5, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions CIP-0030/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,23 @@ Errors: `APIError`, `PaginateError`

If `amount` is `undefined`, this shall return a list of all UTXOs (unspent transaction outputs) controlled by the wallet. If `amount` is not `undefined`, this request shall be limited to just the UTXOs that are required to reach the combined ADA/multiasset value target specified in `amount`, and if this cannot be attained, `undefined` shall be returned. The results can be further paginated by `paginate` if it is not `undefined`.

### api.getCollateral(params: { amount: cbor\<Coin> }): Promise\<TransactionUnspentOutput[] | null>

Errors: `APIError`

The function takes a required object with parameters. With a single **required** parameter for now: `amount`. (**NOTE:** some wallets may be ignoring the amount parameter, in which case it might be possible to call the function without it, but this behavior is not recommended!). Reasons why the `amount` parameter is required:
1. Dapps must be motivated to understand what they are doing with the collateral, in case they decide to handle it manually.
2. Depending on the specific wallet implementation, requesting more collateral than necessarily might worsen the user experience with that dapp, requiring the wallet to make explicit wallet reorganisation when it is not necessary and can be avoided.
3. If dapps don't understand how much collateral they actually need to make their transactions work - they are placing more user funds than necessary in risk.

So requiring the `amount` parameter would be a by-spec behavior for a wallet. Not requiring it is possible, but not specified, so dapps should not rely on that and the behavior is not recommended.

This shall return a list of one or more UTXOs (unspent transaction outputs) controlled by the wallet that are required to reach **AT LEAST** the combined ADA value target specified in `amount` **AND** the best suitable to be used as collateral inputs for transactions with plutus script inputs (pure ADA-only utxos). If this cannot be attained, an error message with an explanation of the blocking problem shall be returned. **NOTE:** wallets are free to return utxos that add up to a **greater** total ADA value than requested in the `amount` parameter, but wallets must never return any result where utxos would sum up to a smaller total ADA value, instead in a case like that an error message must be returned.

The main point is to allow the wallet to encapsulate all the logic required to handle, maintain, and create (possibly on-demand) the UTXOs suitable for collateral inputs. For example, whenever attempting to create a plutus-input transaction the dapp might encounter a case when the set of all user UTXOs don't have any pure entries at all, which are required for the collateral, in which case the dapp itself is forced to try and handle the creation of the suitable entries by itself. If a wallet implements this function it allows the dapp to not care whether the suitable utxos exist among all utxos, or whether they have been stored in a separate address chain (see https://github.com/cardano-foundation/CIPs/pull/104), or whether they have to be created at the moment on-demand - the wallet guarantees that the dapp will receive enough utxos to cover the requested amount, or get an error in case it is technically impossible to get collateral in the wallet (e.g. user does not have enough ADA at all).

The `amount` parameter is required, specified as a `string` (BigNumber) or a `number`, and the maximum allowed value must be agreed to be something like 5 ADA. Not limiting the maximum possible value might force the wallet to attempt to purify an unreasonable amount of ADA just because the dapp is doing something weird. Since by protocol the required collateral amount is always a percentage of the transaction fee, it seems that the 5 ADA limit should be enough for the foreseable future.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fyi both ccvault and Flint use 5~20 ADA and I think Nami does <50 ADA

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that really necessary? Since the collateral is a percentage of a fee - can we imagine a transaction with a 20+ ADA fee?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bottom of the range (5ADA) is what is meant to make sure you have enough collateral to cover any requirement

The upper part of the range (20ADA / 50 ADA) is just because wallets wants to protect users from accidentally losing a lot of ADA due to a poorly programmed dApp and so they don't want to allow using millions of ADA as collateral. 20/50 was picked as an arbitrary cutoff point so that it's not the end of the world if you lose it.

Copy link
Contributor Author

@vsubhuman vsubhuman Feb 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like it then can be just the range from 5 ADA min to 5 ADA max. I.e. if we assume 5 ADA should be enough to cover any requirements then why give dapps any idea to ever have more than that at all? 🤔

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the user may have a 10 ADA utxo entry by chance, and it would be a bit excessive to say to the user "sorry, you can't use your 10 ADA as collateral because it has to be exactly 5 ADA".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the user may have a 10 ADA utxo entry by chance, and it would be a bit excessive to say to the user "sorry, you can't use your 10 ADA as collateral because it has to be exactly 5 ADA".

I am confused here. What will happen with the dapp call to getCollateral in case they specify they want to get 20 ADA, but there's no UTXO below 50 ADA, for example?

The whole point of what I am describing in the spec is that the amount parameter limit should be something like 5 ADA, so that DAPPS can NOT request amounts above 5 ADA. But then the wallet is free to return anything as long as it covers the amount the dapp has requested.

Example:

  1. Dapp requests 3 ADA
  2. Wallet sees there's a 10 ADA utxo
  3. Wallet returns the 10 ADA utxo if the wallet wants
  4. Dapp doesn't care and just includes it into the tx without having to think

Example 2:

  1. Dapp requests 3 ADA
  2. Wallet see there are few utxos of 1.4 ADA
  3. Wallet returns 3 utxos like [1.4 , 1.4 , 1.4] total sum of 4.2
  4. Dapp doesn't care and just includes it into the tx without having to think

Example 3:

  1. Dapp requests 7 ADA
  2. Wallets returns an error saying that's too much and shouldn't be reasonable for a collateral

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Main goal is to ENCAPSULATE the logic as much as possible, achieving:

  1. Dapps dont't have to think AT ALL - just specify the minimum total value of collateral you want to get, and don't make it too high

  2. Wallets are free to implement internally anything they want, they can return a 1000 ADA if they want to, the spec doesn't care or control it, as long as it covers the amount requested by the dapp.

The main requirement is that any wallet implementing must either return non-empty array of utxo that is guaranteed to be equal or above the requested amount, OR return no utxos at all, indicating the requested amount is impossible to achieve. So a wallet must never return utxos that would sum up below the requested amount.

@SebastienGllmt what you are talking about is that Flint is returning utxos of AT LEAST 5 ADA, which will mean that it will be automatically compatible with the proposed spec, because the spec proposes that the requested amount is never above 5 ADA, which means Flint will always return same or above


### api.getBalance(): Promise\<cbor\<value>>

Errors: `APIError`
Expand Down