Add dev_portal (#17)

* adds dev_portal

* change project name from dev-portal to dev_portal
This commit is contained in:
João Bordalo
2023-11-27 15:43:37 +00:00
committed by GitHub
parent 0210d39866
commit d0ce54f493
41 changed files with 9033 additions and 3 deletions

View File

@@ -4,6 +4,6 @@ This is the monorepo containing the initial Ark products.
In this repository you can find: In this repository you can find:
* `asp` - a proof of concept of an Ark Service Provider. - `asp` - a proof of concept of an Ark Service Provider.
* `dev-portal` - the website where to find documentation about Ark protocol and products. - `dev_portal` - the website where to find documentation about Ark protocol and products.
* `noah` - the initial Ark wallet, served as CLI. - `noah` - the initial Ark wallet, served as CLI.

20
dev_portal/.gitignore vendored Normal file
View File

@@ -0,0 +1,20 @@
# Dependencies
/node_modules
# Production
/build
# Generated files
.docusaurus
.cache-loader
# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

41
dev_portal/README.md Normal file
View File

@@ -0,0 +1,41 @@
# Website
This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
### Installation
```
$ yarn
```
### Local Development
```
$ yarn start
```
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
### Build
```
$ yarn build
```
This command generates static content into the `build` directory and can be served using any static contents hosting service.
### Deployment
Using SSH:
```
$ USE_SSH=true yarn deploy
```
Not using SSH:
```
$ GIT_USER=<Your GitHub username> yarn deploy
```
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.

View File

@@ -0,0 +1,3 @@
module.exports = {
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
};

View File

@@ -0,0 +1,343 @@
---
slug: liquidity-requirements
title: Understanding Ark Liquidity Requirements
authors: bordalix
tags: [liquidity, ark, bitcoin]
---
## What is Ark?
Ark is a promising second-layer solution for Bitcoin that could help improve the scalability and privacy of the network. It offers the following benefits:
- **No incoming liquidity required**: Receivers can accept payments without having to worry about having enough funds in their wallets.
- **Maintains recipient anonymity**: Ark protects the anonymity of recipients, which is not always possible with other second-layer solutions.
- **Scalable**: Ark is a scalable solution that can help improve the scalability of Bitcoin.
- **Secure**: Ark is a secure solution that is built on top of the Bitcoin blockchain.
All transactions within Ark must be funded by the Ark Service Provider (ASP) in order to achieve these benefits.
This post discusses some considerations on this topic and calculates the funding needs of the ASP.
Refer to [nomenclature docs](./docs/specs/nomenclature) for any doubt
## Ark liquidity requirements
How much BTC can an ASP accept from new users without risking not having enough capital to fund transfers inside Ark? In other words, what percentage of BTC in Ark is transferred in a 1-month period?
<!-- truncate -->
This is similar to the definition of money velocity, as defined by the St. Louis Fed:
> The velocity of money is the frequency at which one unit of currency is used to purchase domestically-produced goods and services within a given time period.
### Money velocity (MV)
Here are some money velocity numbers:
- USD (Q3 2023): 1.327
- Lightning (August 2023): 0.59 per month
If we use a money velocity of 1.00 (for simplicity), this means that each BTC inside the Ark will be spent 1.00 of the time on a given period. Since the ASP must fund all transactions and onboarding, this means that for each 1 BTC added to the Ark, the ASP will need 1 BTC to fund the onboarding and 1 BTC to fund the transfers inside the Ark. With an initial balance of 100 BTC, this results in a limit of 50 BTC allowed to onboard (100 = 50 for onboarding + 50 for trades).
If MV = 0.59, this means that those initial 100 BTC would allow for 62.89 BTC of onboarding, where (100 = 62.89 for onboarding + (69.89 \* 0.59 = 37.11) for trades).
In reality, the money velocity of Ark is likely to be somewhere between 1.00 and 0.59. This means that the ASP will need to have a certain amount of liquidity on hand to fund both onboarded BTC and transfers inside the Ark. The amount of liquidity required will depend on the specific money velocity of Ark, which is not yet known for sure.
Comparison table:
| Money velocity | Balance | +Onboard (BTC) | Inside Ark (BTC) | Transfers (BTC) |
| -------------: | ------: | -------------: | ---------------: | --------------: |
| 0.59 | 100.00 | 62.89 | 0.00 | 37.11 |
| 1.00 | 100.00 | 50.00 | 0.00 | 50.00 |
| 1.327 | 100.00 | 42.97 | 0.00 | 57.03 |
After one month, all the funds used by the ASP, plus the funds sent by the users, become available again. This means that the ASP will have more available liquidity, so it can increase the allowed value for onboards. On the other hand, there is now more capital inside the Ark, so the ASP needs to reserve more capital to fund the transfers:
| Money velocity | Balance | +Onboard (BTC) | Inside Ark (BTC) | Transfers (BTC) |
| -------------: | ------: | -------------: | ---------------: | --------------: |
| 0.59 | 162.89 | 79.11 | 62.89 | 83.78 |
| 1.00 | 150 | 50.00 | 50.00 | 100.00 |
| 1.327 | 142.97 | 36.93 | 42.97 | 57.03 |
Now, what would happen in a one-year period?
### Simulating for 1 year
Columns definition:
- Inside Ark = Accumulated of allowed onboards
- ASP Balance = Initial balance + Inside Ark
- Reserved for trades = Inside Ark \* MV
- Remaining = Balance - Reserved for trades
- Allowed onboards = Remaining / (1 + MV)
Money Velocity: 0.59
| Month | Inside Ark | ASP Balance | Reserved for trades | Remaining | Allowed onboards |
| ----: | :--------: | :---------: | :-----------------: | :-------: | :--------------: |
| 0 | 0.00 | 100.00 | 0.00 | 100.00 | 0.00 |
| 1 | 0.00 | 100.00 | 0.00 | 100.00 | 62.89 |
| 2 | 62.89 | 162.89 | 37.11 | 125.79 | 79.11 |
| 3 | 142.00 | 242.00 | 83.78 | 158.22 | 99.51 |
| 4 | 241.51 | 341.51 | 142.49 | 199.02 | 125.17 |
| 5 | 366.68 | 466.68 | 216.34 | 250.34 | 157.45 |
| 6 | 524.13 | 624.13 | 309.24 | 314.89 | 198.05 |
| 7 | 722.18 | 822.18 | 426.09 | 396.09 | 249.12 |
| 8 | 971.29 | 1,071.29 | 573.06 | 498.23 | 313.35 |
| 9 | 1,284.65 | 1,384.65 | 757.94 | 626.70 | 394.15 |
| 10 | 1,678.80 | 1,778.80 | 990.49 | 788.31 | 495.79 |
| 11 | 2,174.59 | 2,274.59 | 1,283.01 | 991.58 | 623.64 |
| 12 | 2,798.23 | 2,898.23 | 1,650.95 | 1,247.27 | 784.45 |
Money Velocity: 1
| Month | Inside Ark | ASP Balance | Reserved for trades | Remaining | Allowed onboards |
| ----: | :--------: | :---------: | :-----------------: | :-------: | :--------------: |
| 0 | 0.00 | 100.00 | 0.00 | 100.00 | 0.00 |
| 1 | 0.00 | 100.00 | 0.00 | 100.00 | 50.00 |
| 2 | 50.00 | 150.00 | 50.00 | 100.00 | 50.00 |
| 3 | 100.00 | 200.00 | 100.00 | 100.00 | 50.00 |
| 4 | 150.00 | 250.00 | 150.00 | 100.00 | 50.00 |
| 5 | 200.00 | 300.00 | 200.00 | 100.00 | 50.00 |
| 6 | 250.00 | 350.00 | 250.00 | 100.00 | 50.00 |
| 7 | 300.00 | 400.00 | 300.00 | 100.00 | 50.00 |
| 8 | 350.00 | 450.00 | 350.00 | 100.00 | 50.00 |
| 9 | 400.00 | 500.00 | 400.00 | 100.00 | 50.00 |
| 10 | 450.00 | 550.00 | 450.00 | 100.00 | 50.00 |
| 11 | 500.00 | 600.00 | 500.00 | 100.00 | 50.00 |
| 12 | 550.00 | 650.00 | 550.00 | 100.00 | 50.00 |
Money Velocity 1.327
| Month | Inside Ark | ASP Balance | Reserved for trades | Remaining | Allowed onboards |
| ----: | :--------: | :---------: | :-----------------: | :-------: | :--------------: |
| 0 | 0.00 | 100.00 | 0.00 | 100.00 | 0.00 |
| 1 | 0.00 | 100.00 | 0.00 | 100.00 | 42.97 |
| 2 | 42.97 | 142.97 | 57.03 | 85.95 | 36.93 |
| 3 | 79.91 | 179.91 | 106.04 | 73.87 | 31.74 |
| 4 | 111.65 | 211.65 | 148.16 | 63.49 | 27.28 |
| 5 | 138.94 | 238.94 | 184.37 | 54.57 | 23.45 |
| 6 | 162.39 | 262.39 | 215.49 | 46.90 | 20.15 |
| 7 | 182.54 | 282.54 | 242.23 | 40.31 | 17.32 |
| 8 | 199.86 | 299.86 | 265.22 | 34.64 | 14.89 |
| 9 | 214.75 | 314.75 | 284.98 | 29.78 | 12.80 |
| 10 | 227.55 | 327.55 | 301.96 | 25.59 | 11.00 |
| 11 | 238.55 | 338.55 | 316.55 | 22.00 | 9.45 |
| 12 | 248.00 | 348.00 | 329.09 | 18.90 | 8.12 |
:::info Results
Simulating the three different MV values over a one-year period, we can conclude the following:
- If MV < 1, the ASP can onboard more BTC each month than in the previous month.
- If MV = 1, the allowed value for onboarding BTC is always the same (half of the initial balance).
- If MV > 1, the value of allowed BTC to onboard converges to 0 over time, with the maximum onboard value equal to (initial balance) / (MV - 1).
:::
:::note
The money velocity (MV) for USD is quarterly. Assuming that M2 is constant and GDP is evenly distributed over the three months, the MV for one month should be ⅓ of the MV for the quarter, or 0.33.
:::
### Algorithm
#### Allowed onboard value
The value of allowed onboard BTC for this round will be:
:::info Allowed onboard formula
(Available balance - Users funds in Ark \* MV) / (1 + MV)
:::
Where:
- Available balance = Initial ASP balance + Users funds
- Users funds = All BTC onboarded by users until now
- MV = Money Velocity
#### Money velocity
To calculate the value of Money Velocity:
:::info Money Velocity formula
Average for the last N rounds of (amount transferred / users funds)
:::
#### Rational
The ASP keeps records of onboarded and transferred amounts from previous rounds, and uses them to calculate the money velocity (MV) for the current round. It then uses the MV to calculate the maximum amount that can be onboarded in the current round.
If you've read this far, thank you! But now it's time for the bad news.
## The UTXO model
<details>
<summary>How the UTXO Model Works</summary>
In the UTXO model, each unit of cryptocurrency is treated as a unique and indivisible entity. When a user spends cryptocurrency, they are not actually spending their entire balance. Instead, they are spending specific UTXOs that they own.
Each UTXO has two important pieces of information:
- The amount of cryptocurrency: This is the value of the UTXO.
- A locking script: This is a script that specifies how the UTXO can be spent. The locking script typically requires a digital signature from the owner of the UTXO.
When a user wants to spend cryptocurrency, they create a new transaction. This transaction has two parts:
- Inputs: These are the UTXOs that the user is spending.
- Outputs: These are the new UTXOs that will be created as a result of the transaction.
The locking scripts of the input UTXOs must be satisfied in order for the transaction to be valid. This ensures that only the rightful owner of the cryptocurrency can spend it.
</details>
### The change problem
But since Ark uses a UTXO model, this MV theory doesn't work, as the ASP will also need to fund the change on each transaction. For example, if Alice has a 1 BTC VTXO and wants to pay Bob 0.2 BTC, the ASP will need to fund two new VTXOs:
- 0.2 BTC to Bob
- 0.8 BTC to Alice (change)
#### Some simulations
Imagine that Alice boarded the Ark with 1 BTC. She has a 1 BTC VTXO and spends ⅓ of her money in the first month (MV = 0.33) using three payments of 0.11 BTC each.
Let's also assume that these payments are inside Ark (to Bob), which means that the ASP will also need to fund Bob's VTXO.
| Payment | Value | Alice VTXO | Bob VTXOs<br />(0.11 each) | Liquidity needed | Liquidity accum |
| :-----: | :---: | :--------: | :------------------------: | :--------------: | :-------------: |
| 0 | 0 | 1.00 | 0 | 0 | 0 |
| 1 | 0.11 | 0.89 | 1 | 1.00 | 1.00 |
| 2 | 0.11 | 0.78 | 2 | 0.89 | 1.89 |
| 3 | 0.11 | 0.67 | 3 | 0.78 | **2.67** |
At the end of the transaction, Alice has one VTXO of 0.67 BTC and Bob has three VTXOs of 0.11 BTC each.
:::danger Huge funding needs (factor of **8**)
The ASP needed **2.67** of liquidity to support **0.33** traded inside Ark.
:::
Things get much worse if the user makes 10 payments instead of 3 (spending 0.033 BTC on each):
| Payment | Value | Alice VTXO | Bob VTXOs<br />(0.033 each) | Liquidity needed | Liquidity accum |
| :-----: | :---: | :--------: | :-------------------------: | :--------------: | :-------------: |
| 0 | 0 | 1.00 | 0 | 0 | 0 |
| 1 | 0.033 | 0.97 | 1 | 1.00 | 1.00 |
| 2 | 0.033 | 0.93 | 2 | 0.97 | 1.97 |
| 3 | 0.033 | 0.90 | 3 | 0.93 | 2.90 |
| 4 | 0.033 | 0.87 | 4 | 0.90 | 3.80 |
| 5 | 0.033 | 0.84 | 5 | 0.87 | 4.67 |
| 6 | 0.033 | 0.80 | 6 | 0.84 | 5.51 |
| 7 | 0.033 | 0.77 | 7 | 0.80 | 6.31 |
| 8 | 0.033 | 0.74 | 8 | 0.77 | 7.08 |
| 9 | 0.033 | 0.70 | 9 | 0.74 | 7.81 |
| 10 | 0.033 | 0.67 | 10 | 0.70 | **8.52** |
:::danger Huge funding needs (factor of **25**)
The ASP needed **8.52** of liquidity to support **0.33** traded inside Ark.
:::
### Possible mitigations
One can try to reduce these liquidity requirements by pushing several levers:
- Reduce MV by reducing the timelock (e.g., 2 weeks instead of 1 month).
- Reduce transaction change by creating a set of UTXOs with a range of values on the first place, and then doing coin selection with the purpose of reducing change to the minimum possible.
#### Reduce transaction change
- Assuming MV = 0.33, and 10 payments of equal value during a month period
- Dividing Alices initial UTXO into 10, 100, and 1000 VTXOs
Using a 1:10 ratio for VTXOs:
| VTXO Value | Payment<br />number | Payment<br />value | VTXOs used | Alice balance | Alice VTXOs | Liquidity needed | Liquidity accum |
| :--------: | :-----------------: | :----------------: | :--------: | :-----------: | :---------: | :--------------: | :-------------: |
| 0.1 | 0 | 0.000 | 0 | 1.000 | 10 | 0.0 | 0.00 |
| 0.1 | 1 | 0.033 | 1 | 0.967 | 10 | 0.1 | 0.10 |
| 0.1 | 2 | 0.033 | 1 | 0.934 | 10 | 0.1 | 0.20 |
| 0.1 | 3 | 0.033 | 1 | 0.901 | 10 | 0.1 | 0.30 |
| 0.1 | 4 | 0.033 | 1 | 0.868 | 10 | 0.1 | 0.40 |
| 0.1 | 5 | 0.033 | 1 | 0.835 | 10 | 0.1 | 0.50 |
| 0.1 | 6 | 0.033 | 1 | 0.802 | 10 | 0.1 | 0.60 |
| 0.1 | 7 | 0.033 | 1 | 0.769 | 10 | 0.1 | 0.70 |
| 0.1 | 8 | 0.033 | 1 | 0.736 | 10 | 0.1 | 0.80 |
| 0.1 | 9 | 0.033 | 1 | 0.703 | 10 | 0.1 | 0.90 |
| 0.1 | 10 | 0.033 | 1 | 0.670 | 10 | 0.1 | 1.00 |
Using a 1:100 ratio for VTXOs:
| VTXO Value | Payment<br />number | Payment<br />value | VTXOs used | Alice balance | Alice VTXOs | Liquidity needed | Liquidity accum |
| :--------: | :-----------------: | :----------------: | :--------: | :-----------: | :---------: | :--------------: | :-------------: |
| 0.01 | 0 | 0.000 | 0 | 1.000 | 100 | 0.0 | 0.00 |
| 0.01 | 1 | 0.033 | 4 | 0.967 | 97 | 0.04 | 0.04 |
| 0.01 | 2 | 0.033 | 4 | 0.934 | 94 | 0.04 | 0.08 |
| 0.01 | 3 | 0.033 | 4 | 0.901 | 91 | 0.04 | 0.12 |
| 0.01 | 4 | 0.033 | 4 | 0.868 | 88 | 0.04 | 0.16 |
| 0.01 | 5 | 0.033 | 4 | 0.835 | 85 | 0.04 | 0.20 |
| 0.01 | 6 | 0.033 | 4 | 0.802 | 82 | 0.04 | 0.24 |
| 0.01 | 7 | 0.033 | 4 | 0.769 | 79 | 0.04 | 0.28 |
| 0.01 | 8 | 0.033 | 4 | 0.736 | 76 | 0.04 | 0.32 |
| 0.01 | 9 | 0.033 | 4 | 0.703 | 73 | 0.04 | 0.36 |
| 0.01 | 10 | 0.033 | 4 | 0.670 | 70 | 0.04 | 0.40 |
Using a 1:1000 ratio for VTXOs:
| VTXO Value | Payment<br />number | Payment<br />value | VTXOs used | Alice balance | Alice VTXOs | Liquidity needed | Liquidity accum |
| :--------: | :-----------------: | :----------------: | :--------: | :-----------: | :---------: | :--------------: | :-------------: |
| 0.001 | 0 | 0.000 | 0 | 1.000 | 1000 | 0.0 | 0.00 |
| 0.001 | 1 | 0.033 | 33 | 0.967 | 968 | 0.033 | 0.03 |
| 0.001 | 2 | 0.033 | 33 | 0.934 | 936 | 0.033 | 0.07 |
| 0.001 | 3 | 0.033 | 33 | 0.901 | 904 | 0.033 | 0.10 |
| 0.001 | 4 | 0.033 | 33 | 0.868 | 872 | 0.033 | 0.13 |
| 0.001 | 5 | 0.033 | 33 | 0.835 | 840 | 0.033 | 0.17 |
| 0.001 | 6 | 0.033 | 33 | 0.802 | 808 | 0.033 | 0.20 |
| 0.001 | 7 | 0.033 | 33 | 0.769 | 776 | 0.033 | 0.23 |
| 0.001 | 8 | 0.033 | 33 | 0.736 | 744 | 0.033 | 0.26 |
| 0.001 | 9 | 0.033 | 33 | 0.703 | 712 | 0.033 | 0.30 |
| 0.001 | 10 | 0.033 | 33 | 0.670 | 680 | 0.033 | 0.33 |
Comparison table:
| VTXO ratio | MV | # Payments | ASP liquidity needed |
| ---------: | ---: | ---------: | -------------------: |
| 10 | 0.33 | 10 | 1.00 |
| 100 | 0.33 | 10 | 0.40 |
| 1000 | 0.33 | 10 | 0.33 |
:::info conclusion
Dividing the initial UTXO into more VTXOs decreases the need for funding.
:::
## Conclusion
The liquidity requirements for an ASP will depend on three major factors:
- **Money velocity**: This is not under the control of the ASP, and if it is higher than 1, the Ark capacity will converge to a fixed value.
- **The locktime period on VTXOs**: Reducing the locktime period will return the locked liquidity sooner. However, this also means that users will need to "recycle" their VTXOs sooner, which can be seen as a worse user experience.
- **The VTXO ratio**: In other words, this is the maximum allowed value for a given VTXO. At one extreme, the ASP could force all VTXOs to be of 1 sat, which would eliminate any "wasted" liquidity on change. However, this would also require millions of signatures from the user and ASP to construct a payment, which would cause a worse user experience.
## References
- Velocity of M2 Money Stock
by St Louis Fed
https://fred.stlouisfed.org/series/M2V
- Lightning Report
by River
https://river.com/learn/files/river-lightning-report-2023.pdf
- Cryptocurrencies and the Velocity of Money
by Ingolf Gunnar Anton Pernice, Georg Gentzen, and Hermann Elendner
https://cryptoeconomicsystems.pubpub.org/pub/pernice-cryptocurrencies-velocity/release/9

View File

@@ -0,0 +1,5 @@
bordalix:
name: João Bordalo
title: Developer
url: https://github.com/bordalix
image_url: https://github.com/bordalix.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

31
dev_portal/docs/intro.md Normal file
View File

@@ -0,0 +1,31 @@
---
title: 'Introduction'
sidebar_position: 1
slug: /
---
Welcome to Ark's documentation. Here you can learn more about the protocol, how to join the Ark and spend your coins off-chain in a fast and secure way.
- Be part of the community [joining our Telegram channel](https://t.me/ark_network_community).
- To report bugs or ask for support [open an issue on the Github repository](https://github.com/ark-network/support/issues/new).
- To propose improvements on protocol [open an issue on the Github repository](https://github.com/ark-network/boats/issues/new).
### What is Ark?
Ark is a second-layer solution designed to help scale Bitcoin transactions by using a shared utxo model that enables anonymous, off-chain payments through an untrusted intermediary called the Ark Service Provider (ASP). ASPs are always-on servers that provide liquidity to the network, similar to how Lightning service providers work.
Ark is a scaling category of its own and is not a state channel design or a rollup. Ark is a liquidity network like Lightning that operates without introducing liquidity constraints or a direct link between the sender and receiver. It uses virtual utxos, to enable anonymous, scalable, off-chain payments.
## Get started
### [Join the Ark](user/intro.md)
### [Create the Ark](provider/intro.md)
## Protocol Specifications
[Learn more about Ark](specs/00-index.md)
## Copyright
By contributing to this repository, you agree to license your work under the MIT license unless specified otherwise at the top of the file itself. Any work contributed where you are not the original author must contain its license header with the original author(s) and source.

View File

@@ -0,0 +1,4 @@
{
"label": "Create an Ark",
"position": 4
}

View File

@@ -0,0 +1,4 @@
{
"label": "Coordinator",
"position": 3
}

View File

@@ -0,0 +1,46 @@
---
sidebar_position: 5
title: Configure the CLI
---
Now that your service is up and running you can configure the `coordinator` CLI to interact with it.
The CLI makes use of a configuration file stored in its datadir - defaults to `~/.coordinator-cli` on Linux, `~/Library/Application\ Support/Coordinator-cli` on MacOS.
You can customize the datadir path of your coordinator cli by exporting the environment variable `export ARK_COORDINATOR_CLI_DATADIR=path/to/datadir`.
:::tip
Add this env var to your bash profile otherwise you'll need to always export it when running `coordinator` commands.
:::
You can manage the configuration of your CLI with the features of the `coordinator config` command. Following, you can learn all what you can do with this command.
### Initialize CLI config
You can initialize the configuration of your CLI by the means of flags
```bash
$ coordinator config init
```
This command brings the configuration of your CLI to its default status unless you don't specify a flag for those params you want to tweak.
Run `coordinator config init --help` to see all available configuration flags.
### Customize CLI config
You can change granular params of the CLI's configuration by using the `set` subcommand as shown below:
```bash
$ coordinator config set no-tls true
```
### Show CLI config
You can take a look at the configuration of your CLI with:
```bash
$ coordinator config
```
You've learned everything about configuring the CLI, let's see how it does let you interact with the Coordinator.

View File

@@ -0,0 +1,26 @@
---
sidebar_position: 4
title: Configure the Coordinator
---
The Coordinator can be configured by exporting environment variables at startup, or by adding a configuration file to its datadir.
### Configure with environment variables
The following table lists all the environment variables available, along with a brief description and their default values:
| Name | Description | Default Value |
|---|---|---|
| ARK_COORDINATOR_DATADIR | Let's you change the service's datadir path | `~/.coordinatord` (Linux).<br/><br/>`~/Library/Application\ Support/Coordinatord` (MacOS). |
### Configure with file
You can configure the Coordinator by adding a `config.json` file to its datadir.
Below, you can see all the props you can add to the config file:
```json
{
//TBD
}
```

View File

@@ -0,0 +1,17 @@
---
sidebar_position: 1
title: Overview
---
# Ark Coordinator
The Coordinator handles the perpetual creation of new Ark rounds every 5 seconds.
It can be served in one of the following ways:
* [Dockerized application](run-docker.md)
* [Standalone application](run-standalone.md)
<!-- any dependency? -->
Once your coordinator is up and running you can [configure the CLI](configure-cli.md) to interact with it.

View File

@@ -0,0 +1,30 @@
---
sidebar_position: 3
title: Run with Docker
---
The Coordinator can be served as a dockerized application by following the steps below:
1. Install [Docker](https://docs.docker.com/engine/install) - if you're on Linux, don't forget the [post-installation steps](https://docs.docker.com/engine/install/linux-postinstall/)!
2. Download the latest image of the connector with `docker pull ghcr.io/ark-network/coordinatord:latest`
3. Create a `coordinatord/` folder in your current directory - to mount the datadir as external volume - and start the dockerized service with
```bash
$ docker run -it -d --name coordinatord \
-u
-v "$(pwd)/coordinatord:/home/ark/.coordinatord" \
-e ARK_COORDINATOR_LOG_LEVEL=5 \
ghcr.io/ark-network/coordinatord:latest
```
You can check the logs of the service at anytime by running `docker logs coordinatord`.
The dockerized Coordinator can be configured by the means of environment variables or by adding a `config.json` file to the `coordinatord/` folder you've created. Learn more about this by visiting [this section](configure-service.md).
The service comes also with an embedded CLI, so it's enough for you to create an alias like the following to use it:
```bash
$ alias coordinator="docker exec coordinatord coordinator"
```
Take a look at how to [configure the CLI](configure-cli.md) before start interacting with the running Coordinator.

View File

@@ -0,0 +1,23 @@
---
sidebar_position: 2
title: Run Standalone
---
The Coordinator can be served as a standalone binary by following the steps below:
1. Download the lastest [release](https://github.com/ark-network/ark-coordinator/releases) of the service and the CLI for Linux or MacOS.
2. Rename the binaries `coordinatord` and `coordinator` , move them to your _PATH_ (eg. `/usr/local/bin`), and grant them exec permissions with `chmod +x /usr/local/bin/coordinatord` and `chmod +x /usr/local/bin/coordinator`.
3. Start the service with
```bash
ARK_COORDINATOR_LOG_LEVEL=5
coordinatord & > ~/ark-logs/coordinator.logs.txt &
```
The command above redirects all the logs to the file `~/ark-logs/coordinator.logs.txt`. Therefore you can check the logs of the service at anytime by consulting that file.
The Coordinator service makes use of a datadir - defaults to `~/.coordinatord` on Linux, `~/Library/Application\ Support/Coordinatord` on MacOS - that can be customized by exporting the environment variable `export ARK_COORDINATOR_DATADIR=path/to/datadir` at its startup.
You can configure the Coordinator by the means of environment variables or by adding a `config.json` file to the service's datadir. Learn more about this by visiting [this section](configure-service.md).
Once the service is started you can [configure the CLI](configure-cli.md) and start interacting with it.

View File

@@ -0,0 +1,56 @@
---
sidebar_position: 6
title: Use the CLI
---
Now that your CLI is configured to connect with the running Coordinator, let's take a look at what it makes you capable of.
### List pool transactions
You can retrieve the list of pool transactions made in a certain time range with:
```bash
$ coordinator pools --start --end
```
You can omit the `--end` flag if you want to retrieve all pool transactions from a certain time unitl now.
For each pool tx, you can see details like the txid, status, and amount of liquidity added to the Ark.
You can also list all pool transactions created so far with:
```bash
$ coordinator pools --all
```
Run `coordinators pools --help` to see the full list of available flags.
### Get pool transaction details
You can get details about a specific pool transaction with:
```bash
$ coordinator pool --id <txid>
```
### Register inputs and outptus
You can manually register the VTXOs you're going to spend and the related receivers with:
```bash
$ coordinator register --inputs '[{"txid": "<txid>", "vout": <vout>}]' --outputs '[{"pubkey": "<pubkey>", "amount": <amount>}]'
```
The Coordinator answers with a message containing the virtual (forfeit) transaction spending your coins and the list of all the new VTXOs created in the next round - including those you registered.
<!-- Ref to some toool that allows to revealing the congestion control tree -->
### Finalize input and outputs
Once you signed the virtual transaction you can send it back to the Coordinator and finalize the process with:
```bash
$ coordinator finalize --vtx <signed_vtx>
```
In response you get the id of the pool transaction that is going to be broadcasted by the server.

View File

@@ -0,0 +1,4 @@
{
"label": "Gateway",
"position": 2
}

View File

@@ -0,0 +1,8 @@
---
sidebar_position: 1
title: Overview
---
# Ark Gateway
The Gateway handles users' requests to onboard (join) and offboard (leave) the Ark.

View File

@@ -0,0 +1,11 @@
---
sidebar_position: 1
---
# Ark Service Provider
The Ark Service Provider (ASP) is composed by 3 services that have different responsibilities:
- Gateway, handles (on/off)boarding requests
- Coordinator, handles coinjoin rounds and creation of pool txs (every 5 secs)
- Treasury, handles verification & approval of pool txs, and operations altering the capacity of the service

View File

@@ -0,0 +1,4 @@
{
"label": "Treasury",
"position": 4
}

View File

@@ -0,0 +1,10 @@
---
sidebar_position: 1
title: Overview
---
# Ark Treasury
The Treasury is in charge of verifying and approving pool transactions created by the Coordinator.
It does also handles the management of the ASP capacity - ie. depositing or removing funds - and liquidity - monitoring/sweeping expired VTXOs.

View File

@@ -0,0 +1,24 @@
---
sidebar_position: 1
title: 'BOAT#0: Index'
---
# Index and Overview
Welcome! These **Basics of Ark Technology (BOAT)** documents describe the Ark protocol, a second layer solution that enables anonymous, off-chain payments through an untrusted intermediary that provides liquidity to the network.
## Index
- [BOAT #0: Index](00-index.md)
## Overview
Ark is a second-layer solution designed to help scale Bitcoin transactions by using a shared utxo model that enables anonymous, off-chain payments through an untrusted intermediary called the Ark Service Provider (**ASP**). ASPs are always-on servers that provide liquidity to the network, similar to how Lightning service providers work.
Ark has a utxo set that lives off the chain. These utxos are referred to as virtual utxos or **VTXOs** in short. VTXOs are like short-lived notes that expire after four weeks. Users must spend their VTXOs upon receiving them within this four-week timeframe or return them to themselves to reset the four-week timer.
Users can acquire VTXOs from someone who already owns them or use a process called **onboarding**, which is an atomic two-way peg mechanism that doesn't require trust. Onboarding lets users lift their on-chain utxos off the chain for a 1:1 virtual utxo. Users can unilaterally redeem a virtual utxo for an on-chain utxo without asking for ASP cooperation.
When sending funds, users coin-select and redeem their VTXOs and create new ones for the recipient (plus change) in a coinjoin round where ASP is the blinded coordinator. ASP funds the coinjoin with their own on-chain funds in exchange for VTXO redemptions. Therefore, the coinjoin transaction that hits on-chain has only one or a few inputs provided by the ASP.
The newly created VTXOs of the coinjoin round are bundled and nested under a shared transaction output. This shared output expires four weeks after its creation, and once it expires, the ASP who funded the shared output in the first place can solely sweep the shared output. All nested VTXOs under this shared output are expected to be redeemed in this window period.

View File

@@ -0,0 +1,4 @@
{
"label": "Protocol",
"position": 2
}

View File

@@ -0,0 +1,91 @@
---
sidebar_position: 2
title: 'Nomenclature'
---
## Intervenients
### ASP
Ark is a second-layer solution designed to help scale Bitcoin transactions by using a shared UTXO model that enables anonymous, off-chain payments through an untrusted intermediary called the **Ark Service Provider** (ASP). ASPs are always-on servers that provide liquidity to the network, similar to how Lightning service providers work.
### Users
Any user that onboards the Ark or receives a payment inside an Ark.
### VTXO
Ark has a UTXO set that lives off the chain. These utxos are referred to as virtual UTXOs or VTXOs in short.
## Moments
### Onboarding the Ark
When a User sends funds to the Ark and gets VTXOs in return.
### Unilateral exit
When a user decides to withdraw his funds from the Ark to mainchain, without asking the ASP.
### Round
Periodic transaction crafted by the ASP that hits mainchain and creates new VTXOs.
## Transactions
**Note:** In an optimistic scenario, transactions marked with a **\*** should never hit onchain.
### Funding transaction
- When Alice wants to enter the Ark
| Inputs | Outputs (locking script) |
| ------------------- | ----------------------------------- |
| Alices segwit UTXO | `(Alice + ASP) or (ASP in 1 month)` |
### Redeem transaction \*
- Insurance for Alice, in case the ASP stops responding
- Allows Alice to receive funds back from the Ark
| Inputs | Outputs |
| ------------------------------------------ | -------------------------------------- |
| Funding transaction spending `Alice + ASP` | `(Alice + ASP) or (Alice in 24 hours)` |
### Forfeit transaction \*
- Insurance for the ASP, in case Alice tries to double spend her VTXO after spending it inside Ark
- Before the ASP funds Bobs VTXO in the next Pool transaction, he must receive this transaction signed by Alice
- Uses a connector from the next Pool transaction to achieve atomicity
| Inputs | Outputs |
| ----------------------------------------- | ------- |
| Redeem transaction spending `Alice + ASP` | `ASP` |
| Connector from next Pool transaction |
### Pool transaction (aka Ark transaction)
- Funded by the ASP, creates VTXOs
- After 4 weeks, the ASP can get their funds back
- Multisig `n-of-n` where `n` is the number of participants
- A new transaction is broadcasted every 5 seconds
| Inputs | Outputs |
| -------- | ------------------------------------------- |
| ASP UTXO | Shared output: `n-of-n or (ASP in 1 month)` |
### Shared output (aka Shared UTXO)
- Represents a binary tree of transactions
- In an optimistic scenario, this tree is never revealed
![Docusaurus Plushie](../img/shared_output.png)
### VTXO \*
- Similar to Redeem transaction
- Can be broadcasted anytime, on the condition that previous transactions on the transaction tree (up to the Pool transaction) are confirmed or broadcasted at the same time
| Inputs | Outputs |
| --------------------------------------- | -------------------------------------- |
| Previous transaction on the binary tree | `(Alice + ASP) or (Alice in 24 hours)` |

View File

@@ -0,0 +1,51 @@
---
sidebar_position: 3
title: 'Timeline'
---
### Onboarding the Ark
1. Alice creates a [Funding transaction](#funding-transaction):
- adds any segwit output as an input (<u>must be segwit</u>)
- adds output locked by `(Alice + ASP) or (ASP in 1 month)`
- sends it to ASP, not signed
2. Alice receives a [Redeem transaction](#redeem-transaction-) from the ASP:
- signed by the ASP, spends Funding transaction (1) via `Alice + ASP`
- has one output locked by `(Alice + ASP) or (Alice in 24 hours)`
3. Alice signs and broadcasts Funding transaction (1)
- Is now safe for Alice to broadcast this funding transaction because now she can leave anytime with
[Redeem transaction](#redeem-transaction-) (2) spending `Alice in 24h`, i.e. Alice will be able to get
her funds back in 24 hours.
4. ASP (with Alice) prepares next [Pool transaction](#pool-transaction-aka-ark-transaction)
5. Alice creates a [Forfeit transaction](#forfeit-transaction-):
- spends from Redeem transaction (2) via `Alice + ASP`
- adds connector output from Pool transaction (4) as input
- signs (SIGHASH_ALL) and sends it to the ASP
6. ASP broadcasts [Pool transaction](#pool-transaction-aka-ark-transaction) (4)
7. Alice has now a [VTXO](#vtxo)
8. After 1 month ASP spends Funding transaction (1) via `ASP in 1 month`
### Payment to Bob
1. Alice tells ASP to send [VTXO](#vtxo) to Bob
2. ASP (with Alice) prepares next [Pool transaction](#pool-transaction-aka-ark-transaction)
3. Alice creates a [Forfeit transaction](#forfeit-transaction-):
- spends from VTXO (1) via `Alice + ASP`
- adds connector output from Pool transaction (2) as input
- signs (SIGHASH_ALL) and sends it to the ASP
4. ASP broadcasts [Pool transaction](#pool-transaction-aka-ark-transaction)
5. Bob has now a new [VTXO](#vtxo)
6. For at most 4 weeks, Alice will be able to double spend hers [VTXO](#vtxo), but if she does it, the ASP will have time to grab the funds from the [VTXO](#vtxo) to itself using the [Forfeit transaction](#forfeit-transaction-)
### Exiting the Ark
1. Alice tells ASP she wants to trade [VTXO](#vtxo) for UTXO
2. ASP (with Alice) prepares next [Pool transaction](#pool-transaction-aka-ark-transaction):
- an additional output is added, locked by `Alice`
3. Alice creates a [Forfeit transaction](#forfeit-transaction-):
- spends from VTXO (1) with `Alice + ASP`
- adds connector output from Pool transaction (2) as input
- signs it and send it to the ASP
4. ASP broadcasts [Pool transaction](#pool-transaction-aka-ark-transaction)
5. Alice has now a new UTXO
6. For at most 4 weeks, Alice will be able to double spend hers [VTXO](#vtxo), but if she does it, the ASP will have time (24 hours) to grab the funds from the [VTXO](#vtxo) to itself using the [Forfeit transaction](#forfeit-transaction-)

View File

@@ -0,0 +1,4 @@
{
"label": "Join the Ark",
"position": 3
}

View File

@@ -0,0 +1,8 @@
---
sidebar_position: 1
title: Overview
---
You can join the Ark with one of the following apps:
- [Noah CLI](noah-cli.md)

View File

@@ -0,0 +1,70 @@
---
sidebar_position: 2
title: Noah CLI
---
The Noah CLI allows you to interact with the Ark Service Provider (ASP). It is a command line tool that can be used to create and manage your Ark Wallet.
## Configure the CLI
The noah CLI requires a set of variables to be set, use flags to set them.
```bash
noah config connect <ARK_URL>
```
## Set up Noah wallet
`noah init` is a command that sets up a Noah wallet with a 32-bytes private key and a password in order to encrypt the private key.
```bash
noah init --password <PASSWORD> [--prvkey <PRIVATE_KEY>]
```
## Receive VTXO
### Get receiving address
You can use the noah CLI to print your Ark address. This can be used to receive VTXO.
```bash
noah receive
```
:::tip
testnet only: `noah faucet <AMOUNT>` to receive newly created VTXO from the service provider.
:::
### Print balance
```bash
noah balance
```
`balance` returns the sum of all VTXOs belonging to the Noah wallet.
## Send VTXO(s)
```bash
noah send --receivers '[{"to": "<ARK_ADDRESS", "amount": <AMOUNT>}, ...]'
```
Noah CLI is responsible to select the coins to send for the given amount. It will sync with the service provider to forfeit the VTXO(s) and create a new VTXO belonging to the recipient. A change VTXO will be created if needed. Asks user password before signing.
## Redemption
### Collaborative redemption
```bash
noah redeem --address <ONCHAIN_ADDRESS> --amount <AMOUNT>
```
Noah CLI will sync with the service provider in order to redeem onchain the given amount in the next round, any remaining change will become a new vTXO. Asks user password before signing.
### Unilateral redemption
```bash
noah redeem --address <ONCHAIN_ADDRESS> --force
```
With the `--force` flag Noah CLI will unilateraly redeem all VTXOs by signing the psbt(s) and broadcast them. Asks user password before signing.

View File

@@ -0,0 +1,132 @@
// @ts-check
// Note: type annotations allow type checking and IDEs autocompletion
const lightCodeTheme = require('prism-react-renderer/themes/github')
const darkCodeTheme = require('prism-react-renderer/themes/dracula')
/** @type {import('@docusaurus/types').Config} */
const config = {
title: 'Ark',
tagline: 'TBD',
favicon: 'img/ark-logo.png',
url: 'https://dev.arkpill.me',
baseUrl: '/',
organizationName: 'Ark',
projectName: 'dev_portal',
onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'warn',
i18n: {
defaultLocale: 'en',
locales: ['en'],
},
presets: [
[
'classic',
/** @type {import('@docusaurus/preset-classic').Options} */
({
docs: {
sidebarPath: require.resolve('./sidebars.js'),
// Please change this to your repo.
// Remove this to remove the "edit this page" links.
editUrl: 'https://github.com/ark-network/edit/master/dev_portal/',
},
blog: {
showReadingTime: true,
// Please change this to your repo.
// Remove this to remove the "edit this page" links.
editUrl: 'https://github.com/ark-network/edit/main/dev_portal/blog/',
},
theme: {
customCss: require.resolve('./src/css/custom.css'),
},
}),
],
],
themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
// Replace with your project's social card
image: 'img/ark-og-image.png',
navbar: {
title: 'Developer Portal',
logo: {
alt: 'Ark Logo',
src: 'img/ark-logo.png',
srcDark: 'img/ark-logo.png',
},
items: [
{
type: 'docSidebar',
sidebarId: 'tutorialSidebar',
position: 'left',
label: 'Docs',
},
{ to: '/blog', label: 'Blog', position: 'left' },
{
href: 'https://github.com/ark-network',
label: 'GitHub',
position: 'right',
},
],
},
footer: {
links: [
{
title: 'DOCS',
items: [
{
label: 'What Ark is',
to: '/docs/specs/index',
},
{
label: 'Join the Ark',
to: '/docs/user/intro',
},
{
label: 'Create an Ark',
to: '/docs/provider/intro',
},
],
},
{
title: 'COMMUNITY',
items: [
{
label: 'Stack Exchange',
href: 'https://bitcoin.stackexchange.com/questions/tagged/ark',
},
{
label: 'Twitter',
href: 'https://twitter.com/ark-network',
},
],
},
{
title: 'MORE',
items: [
{
label: 'Blog',
to: '/blog',
},
{
label: 'GitHub',
href: 'https://github.com/ark-network',
},
],
},
],
copyright: `Copyright © ${new Date().getFullYear()} Ark. Built with Docusaurus.`,
},
colorMode: {
defaultMode: 'dark',
},
prism: {
theme: lightCodeTheme,
darkTheme: darkCodeTheme,
},
}),
}
module.exports = config

43
dev_portal/package.json Normal file
View File

@@ -0,0 +1,43 @@
{
"name": "dev_portal",
"version": "0.0.0",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
"start": "docusaurus start",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids"
},
"dependencies": {
"@docusaurus/core": "2.4.3",
"@docusaurus/preset-classic": "2.4.3",
"@mdx-js/react": "^1.6.22",
"clsx": "^1.2.1",
"prism-react-renderer": "^1.3.5",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "2.4.3"
},
"browserslist": {
"production": [
">0.5%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"engines": {
"node": ">=16.14"
}
}

33
dev_portal/sidebars.js Normal file
View File

@@ -0,0 +1,33 @@
/**
* Creating a sidebar enables you to:
- create an ordered group of docs
- render a sidebar for each doc of that group
- provide next/previous navigation
The sidebars can be generated from the filesystem, or explicitly defined here.
Create as many sidebars as you want.
*/
// @ts-check
/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
const sidebars = {
// By default, Docusaurus generates a sidebar from the docs folder structure
tutorialSidebar: [{type: 'autogenerated', dirName: '.'}],
// But you can create a sidebar manually
/*
tutorialSidebar: [
'intro',
'hello',
{
type: 'category',
label: 'Tutorial',
items: ['tutorial-basics/create-a-document'],
},
],
*/
};
module.exports = sidebars;

View File

@@ -0,0 +1,57 @@
import React from 'react';
import clsx from 'clsx';
import styles from './styles.module.css';
const FeatureList = [
{
title: 'Fast',
description: (
<>
TBD.
</>
),
},
{
title: 'Secure',
description: (
<>
TBD.
</>
),
},
{
title: 'Convenient',
description: (
<>
TBD.
</>
),
},
];
function Feature({Svg, title, description}) {
return (
<div className={clsx('col col--4')}>
<div className="text--center">
</div>
<div className="text--center padding-horiz--md">
<h3>{title}</h3>
<p>{description}</p>
</div>
</div>
);
}
export default function HomepageFeatures() {
return (
<section className={styles.features}>
<div className="container">
<div className="row">
{FeatureList.map((props, idx) => (
<Feature key={idx} {...props} />
))}
</div>
</div>
</section>
);
}

View File

@@ -0,0 +1,11 @@
.features {
display: flex;
align-items: center;
padding: 2rem 0;
width: 100%;
}
.featureSvg {
height: 200px;
width: 200px;
}

View File

@@ -0,0 +1,30 @@
/**
* Any CSS included here will be global. The classic template
* bundles Infima by default. Infima is a CSS framework designed to
* work well for content-centric websites.
*/
/* You can override the default Infima variables here. */
:root {
--ifm-color-primary: #2e8555;
--ifm-color-primary-dark: #29784c;
--ifm-color-primary-darker: #277148;
--ifm-color-primary-darkest: #205d3b;
--ifm-color-primary-light: #33925d;
--ifm-color-primary-lighter: #359962;
--ifm-color-primary-lightest: #3cad6e;
--ifm-code-font-size: 95%;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
}
/* For readability concerns, you should choose a lighter palette in dark mode. */
[data-theme='dark'] {
--ifm-color-primary: #25c2a0;
--ifm-color-primary-dark: #21af90;
--ifm-color-primary-darker: #1fa588;
--ifm-color-primary-darkest: #1a8870;
--ifm-color-primary-light: #29d5b0;
--ifm-color-primary-lighter: #32d8b4;
--ifm-color-primary-lightest: #4fddbf;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
}

View File

@@ -0,0 +1,45 @@
import React from 'react';
import clsx from 'clsx';
import Link from '@docusaurus/Link';
import Translate from '@docusaurus/Translate'
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import Layout from '@theme/Layout';
import HomepageFeatures from '@site/src/components/HomepageFeatures';
import styles from './index.module.css';
function HomepageHeader() {
const {siteConfig} = useDocusaurusContext();
return (
<header className={clsx('hero hero--primary', styles.heroBanner)}>
<div className="container">
<h1 className="hero__title">{siteConfig.title}</h1>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<div className={styles.buttons}>
<Link className="button button--outline" to="/docs/">
<Translate>DOCS</Translate>
</Link>
<Link
className="button button--outline"
to="/blog">
<Translate>BLOG</Translate>
</Link>
</div>
</div>
</header>
);
}
export default function Home() {
const {siteConfig} = useDocusaurusContext();
return (
<Layout
title={`Hello from ${siteConfig.title}`}
description="Description will go into a meta tag in <head />">
<HomepageHeader />
<main>
<HomepageFeatures />
</main>
</Layout>
);
}

View File

@@ -0,0 +1,23 @@
/**
* CSS files with the .module.css suffix will be treated as CSS modules
* and scoped locally.
*/
.heroBanner {
padding: 4rem 0;
text-align: center;
position: relative;
overflow: hidden;
}
@media screen and (max-width: 996px) {
.heroBanner {
padding: 2rem;
}
}
.buttons {
display: flex;
align-items: center;
justify-content: center;
}

View File

@@ -0,0 +1,7 @@
---
title: Markdown page example
---
# Markdown page example
You don't need React to write simple standalone pages.

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

7711
dev_portal/yarn.lock Normal file

File diff suppressed because it is too large Load Diff