-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merged group 1's demo code into code of group 2
- Loading branch information
Showing
28 changed files
with
3,338 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<vector android:autoMirrored="true" android:height="24dp" | ||
android:viewportHeight="471.26" android:viewportWidth="471.26" | ||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> | ||
<path android:fillColor="#FF000000" android:pathData="M402.24,69.02A235.62,235.62 0,1 0,69.02 402.24,235.62 235.62,0 1,0 402.24,69.02ZM235.63,418.26C134.93,418.26 53,336.33 53,235.63S134.93,53 235.63,53 418.26,134.93 418.26,235.63 336.33,418.26 235.63,418.26Z"/> | ||
<path android:fillColor="#FF000000" android:pathData="M240.03,87.29c-66.59,0 -141.08,47.92 -152.48,110l2.53,-5.1c11.79,-26.07 45,-46.42 84.46,-41.71 35.91,4.28 67.3,33.95 72.24,68.48 5.25,36.61 29.33,63.14 65.5,63.14s65.49,-28.27 65.49,-63.14C377.77,149.16 312.38,87.29 240.03,87.29ZM256.22,122.45c-5.62,-1.9 -7,-9 -5.34,-12.89s6.73,-4 11.79,-3.59a81.29,81.29 0,0 1,17.55 3.85c7.45,2.9 13.76,7.46 17.05,11.26 3.86,4.45 4.25,8.91 2,12.48s-7,3.25 -12.37,0.67c-4.51,-2.18 -6.13,-5.53 -12.85,-8.37C265.94,122.45 262.9,124.71 256.22,122.45ZM310.52,264.63c-2.27,3.57 -5.88,4 -11,3.9 -2.36,-0.06 -7.42,-1.64 -10.45,-3.27a44.84,44.84 0,0 1,-11.12 -8c-4.14,-4.21 -5.38,-9.18 -3.11,-12.75s7.52,-4.09 12.37,-0.67c3,2.1 4.58,3.5 7.29,4.83 3.41,1.67 6.55,2.14 10.95,4.09C310.91,255.19 312.79,261.04 310.52,264.63Z"/> | ||
<path android:fillColor="#FF000000" android:pathData="M377.93,280.01c-11.79,26.07 -45,46.42 -84.46,41.71 -35.91,-4.28 -67.3,-33.95 -72.24,-68.48 -5.25,-36.61 -29.33,-63.14 -65.5,-63.14s-65.49,28.27 -65.49,63.14c0,69.75 65.39,131.62 137.74,131.62 66.59,0 141.08,-47.92 152.48,-110ZM159.63,340.51c-3.11,2.86 -6.73,2.38 -11.59,0.93 -2.26,-0.67 -6.75,-3.5 -9.25,-5.86a44.72,44.72 0,0 1,-8.69 -10.57c-2.9,-5.13 -2.82,-10.25 0.3,-13.12s8.32,-2 12.12,2.56c2.34,2.8 3.52,4.57 5.8,6.55 2.85,2.5 5.77,3.76 9.51,6.78C162.43,331.5 162.73,337.63 159.63,340.51ZM190.84,232.98c-2.27,3.58 -7,3.26 -12.37,0.68 -4.51,-2.19 -6.13,-5.54 -12.85,-8.38 -8.09,-3.41 -11.13,-1.15 -17.81,-3.41 -5.62,-1.9 -7,-9 -5.34,-12.88s6.73,-4.05 11.79,-3.59a81.36,81.36 0,0 1,17.55 3.84c7.45,2.91 13.76,7.47 17.05,11.26C192.7,224.96 193.09,229.42 190.82,232.98Z"/> | ||
</vector> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
<img src="./Title.png" > | ||
|
||
**Liquid Swap** aims to enable the use of liquidity pools for exchanging *any* two currencies, regardless of each currency's implementation. The module is a proof-of-concept Android application implementing a [liquidity pool](https://academy.binance.com/en/articles/what-are-liquidity-pools-in-defi). It allows users to exchange Bitcoin (BTC) and Ether (ETH). Users can provide liquidity to the pool if they wish. Transactions are logged on [TrustChain](https://github.com/Tribler/kotlin-ipv8/blob/master/doc/TrustChainCommunity.md), and the application is part of the [TrustChain Super App](https://github.com/Tribler/trustchain-superapp). The liquidity pool is implemented using two multi-signature wallets: one on a Bitcoin regnet and one on the Ethereum Goerli testnet. | ||
|
||
In the rapidly evolving world of [*Decentralized Finance*](https://en.wikipedia.org/wiki/Decentralized_finance) (DeFi), there is a growing demand for exchanging (crypto)currencies. Current cryptocurrencies usually offer little functionality for cross-interaction. This makes exchanging (crypto)currencies cumbersome, and in many cases a (centralized) third-party is required. Liquidity pools, such as those that use the [Uniswap](https://uniswap.org/) protocol, are a promising alternative to conventional (centralized) exchanges that rely on order books. Uniswap however, is limited to ERC-20 tokens. Hence, the need for new methods to exchange (crypto)currencies. | ||
|
||
## User Interface | ||
|
||
The UI consists of a single view in which the pool's amount of liquidity for each currency can be seen, as well as the user's wallet balances. It also provides three buttons, which the user can use to interact with the pool, such as providing liquidity or trading currency. Finally, a log displays relevant information about the user's and pool's interactions and transactions. | ||
|
||
<img src="./UserInterface.png"> | ||
|
||
## Technical Details | ||
|
||
Liquid swap implements a liquidity pool using Bitcoin multi-signature contracts and an Ethererum multi-signature smart contract, using *[bitcoinj](https://bitcoinj.org/)* for Bitcoin transactions, and a *[geth](https://github.com/ethereum/go-ethereum)* light node for Ethereum transactions. | ||
|
||
Ethereum testnets can take hours to confirm multi-signature transactions, so currently the Ethereum side of the implementation uses *[web3j](https://github.com/web3j/web3j)* with two personal wallets for accessing the Goerli testnet for Ethereum through using an external endpoint ([Infura](https://infura.io/docs/ethereum/wss/faq)). Replacing this with the geth implementation is a matter of seconds, but you should anticipate long confirmation times for transactions with the multi-signature smart contract. | ||
|
||
Similarly, due to performance, the Bitcoin implementation utilizes a regnet chain. It can take a long time for *bitcoinj* to connect to the Bitcoin testnet or mainnet. | ||
|
||
### Project Structure | ||
|
||
The project consists of several packages: | ||
|
||
- `data` - Contains the implementation of all currency wallets, as well as providing the used solidity contract. They can be used and shared throughout the apps in the superapp. | ||
- `ethereum\contracts` | ||
- `geth\MutliSigWallet.java` - Wrapper of compiled solidity contract for geth. | ||
- `web3j\MutliSigWallet.java` - Wrapper of compiled solidity contract for web3j. | ||
- `BitcoinMultiSigWallet.kt` - Implements Bitcoin multi-signature contract using bitcoinj. | ||
- `BitcoinWallet.kt` - Implements personal Bitcoin wallet using bitcoinj. | ||
- `EthereumGethMultiSigWallet.kt` - Implements Ethereum multi-signature smart contract using geth. | ||
- `EthereumGethWallet.kt` - Implements a personal Ethereum wallet using geth. | ||
- `EthereumWeb3jMultiSigWallet.kt` - Implements Ethereum multi-signature smart contract using web3j. | ||
- `EthereumWeb3jWallet.kt` | ||
- `ui` - Contains fragments that implement the logic required the liquidity pool. | ||
- `PoolBitcoinEthereumFragment.kt` - UI fragment that implements pool logic. | ||
- `util` - Contains utility code. | ||
- `TrustChainInteractor.kt` - Handles TrustChain interactions. | ||
|
||
## Limitations | ||
|
||
As with every project, liquid swap has several limitations: | ||
|
||
* Supports only a single currency pair: BTC/ETH | ||
* Currently implements only a single liquidity pool | ||
* Uses a [regnet](#Technical-Details) bitcoin blockchain | ||
* Uses an Ethereum [Infura](#Technical-Details) end-point, which is not decentralized | ||
|
||
### Ethereum Smart Contract Specification | ||
|
||
We used [Gnosis's](https://gnosis.io) contract [implementation](https://github.com/gnosis/MultiSigWallet/blob/master/contracts/MultiSigWallet.sol) of an Ethereum multi-signature wallet contract. (There's also an [implementation](https://github.com/gnosis/MultiSigWallet/blob/master/contracts/MultiSigWalletWithDailyLimit.sol) with a daily limit.) | ||
|
||
This contract maintains a list of (current) wallet owners (of which there can be at most 50 of simultaneously), a list of past transactions (from which the current balance(s) can be derived) and corresponding confirmations, and the required number of signitures for a withdrawal. This latter number is specified during contract creation, together with an (initial) list of at least this number of owner addresses. However, the number of required signatures can still be changed later on, and owners can be added and removed at any time as well. | ||
Owners can submit transactions (withdrawals from the multisignature wallet) signed by them. The contract will then wait for r - 1 signatures from other owners, after which the transaction is confirmed and executed. The contract implementation has a very clear and easy-to-understand interface of functions, which facilitate all this functionality. | ||
|
||
The contract is implemented in Solidity as a `.sol` file. In order to deploy a contract for Android, a Java or Kotlin binding is needed, which is essentially a wrapper class for the contract. In order to generate this binding, the `.sol` file needs to be compiled to two files: an `.abi` file (Application Binary Interface; a binary interface into the contract), and a `.bin` file (the contract compiled to binary code). This compilation can be done by the [`solc`](https://github.com/ethereum/solidity/releases) compiler, or online with [Ethereum's Remix IDE](https://remix.ethereum.org). (Make sure to compile with a compiler version that corresponds to the version of Solidity that the contract specifies, i.e. `0.4.15`.) | ||
The wrapper can then be generated from these `.abi` and `.bin` files in two ways: one for web3j ([using a web3j installation on Linux](https://ethereum.stackexchange.com/a/95217/68439); the Windows version did not work for us) and one for Geth ([using a Geth installation](https://geth.ethereum.org/docs/dapp/native-bindings)). | ||
|
||
## Guides | ||
|
||
### 1. Run a geth *light node* on Android | ||
|
||
It's possible to run an Ethereum light node on Android using *geth*. This allows you to perform actions on Ethereum such as: submit transactions, deploy/interact contracts, and view account balances. | ||
|
||
However, it is important to know that the Android implementation of *geth* does **not** support [JSON-RPC](https://geth.ethereum.org/docs/rpc/server), unlike its Windows/Linux implementations. Hence, although it is possible to run a stand-alone (light) ethereum client on Android, it is not possible to connect *web3j* to it. | ||
|
||
The first step is to import geth in your `build.gradle` file: | ||
```kotlin | ||
implementation group: 'org.ethereum', name:'geth-android-all-1.10.1-c2d2f4ed', ext:'aar' | ||
``` | ||
|
||
A `nodeConfig` is necessary to initialize the node. It contains configuration settings such as which chain to connect to. It can be created as follows: | ||
```kotlin | ||
val nodeConfig = Geth.newNodeConfig() | ||
nodeConfig.ethereumGenesis = Geth.rinkebyGenesis() | ||
``` | ||
|
||
Note that `ethereumGenesis` should be set to the specific testnet that you would like to connect to. | ||
|
||
Finally, start the geth node using: | ||
|
||
```kotlin | ||
node = Geth.newNode(nodeDirectory, nodeConfig) | ||
node.start() | ||
``` | ||
|
||
Now that the node is running, you can interact with the blockchain that you specified. Below you'll find a short example on how to create an Ethereum account, and how to request its balance. | ||
|
||
Initialize a keystore to create an Ethereum account: | ||
```kotlin | ||
keyStore = KeyStore( | ||
keyStoreDirectory, | ||
Geth.LightScryptN, | ||
Geth.LightScryptP | ||
) | ||
``` | ||
|
||
Create an Ethereum account using: | ||
```kotlin | ||
val password = "..." | ||
val account = keyStore.newAccount(password) | ||
|
||
``` | ||
|
||
You have now setup an Ethereum account using a Geth light node on Android, congratulations! Get the account's current balance and address like this: | ||
|
||
```kotlin | ||
val context: Context = Geth.newContext() | ||
val address = account.agethss | ||
val balance = node.ethereumClient.getBalanceAt(context, address, -1) | ||
``` | ||
|
||
Now let's send some funds to another Ethereum address: | ||
```kotlin | ||
val receiveAddress = Address("...") | ||
val amount = BigInt(1000) // 1000 Gwei. | ||
|
||
val transaction = Transaction( | ||
node.ethereumClient.getPendingNonceAt(context, address), // Nonce. | ||
receiveAddress, // Receive address. | ||
amount, // Amount. | ||
10000000, // Gas limit. | ||
BigInt(1), // Gas price. | ||
ByteArray(0) // Data. | ||
) | ||
|
||
val chainId = BigInt(4) // Rinkeby chain id. | ||
val signedTransaction = keyStore.signTxPassphrase(account, password, transaction, chainId) | ||
|
||
send(signedTransaction) | ||
``` | ||
|
||
You can use services like [Etherscan](https://rinkeby.etherscan.io/) to check your transaction status. | ||
|
||
### 2. Web3j on Android | ||
Importing the `web3j` library into the superapp can be problematic due to `org.bouncycastle` being a duplicate dependency. So `web3j` can be imported as follows: | ||
```kotlin | ||
implementation (group: 'org.web3j', name: 'core', version: '4.6.0-android') { | ||
exclude group: 'org.bouncycastle' | ||
} | ||
``` |
Oops, something went wrong.