Skip to content

Commit

Permalink
Merged group 1's demo code into code of group 2
Browse files Browse the repository at this point in the history
  • Loading branch information
thversfelt committed Apr 19, 2021
2 parents d5db8d7 + 2b35fe1 commit b987ea4
Show file tree
Hide file tree
Showing 28 changed files with 3,338 additions and 31 deletions.
9 changes: 9 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@ repositories {
}
}

allprojects {
repositories {
jcenter()
flatDir {
dirs '../common/libs'
}
}
}

dependencies {
implementation project(':common')
implementation project(':trustchain-voter')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ enum class AppDefinition(
EuroTokenMainActivity::class.java
),
LIQUIDITY(
R.drawable.ic_add_black_24dp,
R.drawable.ic_pool,
"Liquidity Pool",
R.color.blue,
LiquidityPoolMainActivity::class.java
Expand Down
2 changes: 2 additions & 0 deletions common/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ dependencies {

implementation group: 'org.bitcoinj', name: 'bitcoinj-core', version: '0.15.10'

implementation group: 'org.bitcoinj', name: 'bitcoinj-core', version: '0.15.10'

// BitTorrent
api files('libs/jlibtorrent-1.2.10.0.jar')
api files('libs/jlibtorrent-android-arm64-1.2.10.0.jar')
Expand Down
Binary file added common/libs/geth-android-all-1.10.1-c2d2f4ed.aar
Binary file not shown.
7 changes: 7 additions & 0 deletions common/src/main/res/drawable/ic_liquid.xml
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>
141 changes: 141 additions & 0 deletions liquidity-pool/README.md
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'
}
```
Loading

0 comments on commit b987ea4

Please sign in to comment.