Skip to content
Open
Show file tree
Hide file tree
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
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -117,5 +117,8 @@
</intent-filter>
</receiver>

<activity
android:name="com.asfoundation.wallet.tokenswap.SwapEtherToTokenActivity"
android:label="SwappMock1Activity"/>
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.asfoundation.wallet.di;

import com.asfoundation.wallet.advertise.WalletPoAService;
import com.asfoundation.wallet.tokenswap.SwapEtherToTokenActivity;
import com.asfoundation.wallet.ui.AddTokenActivity;
import com.asfoundation.wallet.ui.ConfirmationActivity;
import com.asfoundation.wallet.ui.Erc681Receiver;
Expand Down Expand Up @@ -48,6 +49,9 @@
@ActivityScope @ContributesAndroidInjector(modules = ConfirmationModule.class)
abstract IabActivity bindIabModule();

@ActivityScope @ContributesAndroidInjector(modules = ConfirmationModule.class)
abstract SwapEtherToTokenActivity bindSwapEtherToTokenActivity();

@ContributesAndroidInjector abstract MyAddressActivity bindMyAddressModule();

@ActivityScope @ContributesAndroidInjector(modules = TokensModule.class)
Expand Down
27 changes: 25 additions & 2 deletions app/src/main/java/com/asfoundation/wallet/di/ToolsModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@
import com.asfoundation.wallet.service.RealmManager;
import com.asfoundation.wallet.service.TickerService;
import com.asfoundation.wallet.service.TrustWalletTickerService;
import com.asfoundation.wallet.tokenswap.SwapBlockchainWriter;
import com.asfoundation.wallet.tokenswap.SwapDataMapper;
import com.asfoundation.wallet.tokenswap.SwapInteractor;
import com.asfoundation.wallet.tokenswap.SwapProofWriter;
import com.asfoundation.wallet.tokenswap.SwapTransactionFactory;
import com.asfoundation.wallet.ui.AppcoinsApps;
import com.asfoundation.wallet.ui.airdrop.AirdropChainIdMapper;
import com.asfoundation.wallet.ui.airdrop.AirdropInteractor;
Expand Down Expand Up @@ -255,8 +260,9 @@

@Singleton @Provides AppCoinsAddressProxySdk provideAdsContractAddressSdk(
Web3jProvider web3jProvider, FindDefaultWalletInteract findDefaultWalletInteract) {
return new AppCoinsAddressProxyBuilder().createAddressProxySdk(() -> findDefaultWalletInteract.find()
.map(wallet -> wallet.address), web3jProvider::get);
return new AppCoinsAddressProxyBuilder().createAddressProxySdk(
() -> findDefaultWalletInteract.find()
.map(wallet -> wallet.address), web3jProvider::get);
}

@Singleton @Provides HashCalculator provideHashCalculator(Calculator calculator) {
Expand Down Expand Up @@ -343,4 +349,21 @@ List<AppcoinsOperationsDataSaver.OperationDataSource> provideAppcoinsOperationLi
return new AppcoinsApps(new Applications.Builder().setApi(appsApi)
.build());
}

@Singleton @Provides SwapTransactionFactory provideSwapTransactionFactory(
Web3jProvider web3jProvider, EthereumNetworkRepositoryType networkRepositoryType,
AppCoinsAddressProxySdk adsContractAddressProvider, WalletRepositoryType walletRepositoryType,
PasswordStore passwordStore, AccountKeystoreService accountKeystoreService) {
return new SwapTransactionFactory(web3jProvider, networkRepositoryType,
adsContractAddressProvider, walletRepositoryType, passwordStore, accountKeystoreService);
}

@Singleton @Provides SwapProofWriter provideSwapBlockChainWriter(Web3jProvider web3jProvider,
SwapTransactionFactory swapTransactionFactory) {
return new SwapBlockchainWriter(web3jProvider, swapTransactionFactory, new SwapDataMapper());
}

@Singleton @Provides SwapInteractor provideSwapInteractor(SwapProofWriter swapBlockchainWriter) {
return new SwapInteractor(swapBlockchainWriter, new SwapDataMapper());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.asfoundation.wallet.tokenswap;

public interface ResponseListener<T> {
void onResponse(T t);

void onError(Throwable error);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package com.asfoundation.wallet.tokenswap;

import android.annotation.SuppressLint;
import com.asfoundation.wallet.repository.TransactionException;
import com.asfoundation.wallet.repository.Web3jProvider;
import io.reactivex.Single;
import io.reactivex.annotations.Nullable;
import io.reactivex.functions.Consumer;
import java.math.BigInteger;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.FunctionReturnDecoder;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.Uint;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.Response;
import org.web3j.protocol.core.methods.request.Transaction;
import org.web3j.protocol.core.methods.response.EthCall;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
import org.web3j.utils.Numeric;

import static org.web3j.protocol.core.methods.request.Transaction.createEthCallTransaction;

public class SwapBlockchainWriter implements SwapProofWriter {

private final Web3jProvider web3jProvider;
private final SwapTransactionFactory swapTransactionFactory;
private SwapDataMapper swapDataMapper;
private ResponseListener resL;

public SwapBlockchainWriter(Web3jProvider web3jProvider,
SwapTransactionFactory swapTransactionFactory, SwapDataMapper swapDataMapper) {
this.web3jProvider = web3jProvider;
this.swapTransactionFactory = swapTransactionFactory;
this.swapDataMapper = swapDataMapper;
}

@SuppressLint("CheckResult") @Override public void writeSwapProof(SwapProof swapProof) {
swapTransactionFactory.createTransaction(swapProof)
.flatMap(this::sendTransaction)
.subscribe(new Consumer<Object>() {
@Override public void accept(Object result) {
resL.onResponse(result.toString());
}
}, new Consumer<Throwable>() {
@Override public void accept(Throwable error) {
resL.onError(error);
}
});
}

@Override public void setListener(@Nullable ResponseListener listener) {
this.resL = listener;
}

//writes Transactions that are only query from the blockchain
@Override public BigInteger writeGetterSwapProof(SwapProof swapProof) {
String from = swapProof.getFromAddress();
String to = swapProof.getToAddress();
Function getRates = swapDataMapper.getDataExpectedRate(swapProof);
String encodedFunction = FunctionEncoder.encode(getRates);
Transaction ethCallTransaction = createEthCallTransaction(from, to, encodedFunction);
try {
Future<EthCall> rawResponse = web3jProvider.get(swapProof.getChainId())
.ethCall(ethCallTransaction, DefaultBlockParameterName.LATEST)
.sendAsync();
while (!rawResponse.isDone()) {
}
if (!rawResponse.get()
.hasError()) {
List<Type> response = FunctionReturnDecoder.decode(rawResponse.get()
.getValue(), getRates.getOutputParameters());
return ((Uint) response.get(0)).getValue();
} else {
throw new RuntimeException(mapErrorToMessage(rawResponse.get()
.getError()));
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return BigInteger.ZERO;
}

private Single<String> sendTransaction(byte[] transaction) {
return Single.fromCallable(() -> {
EthSendTransaction sentTransaction = web3jProvider.getDefault()
.ethSendRawTransaction(Numeric.toHexString(transaction))
.send();
if (sentTransaction.hasError()) {
throw new TransactionException(sentTransaction.getError()
.getCode(), sentTransaction.getError()
.getMessage(), sentTransaction.getError()
.getData());
}
return sentTransaction.getResult();
});
}

private String mapErrorToMessage(Response.Error error) {
return "Code: "
+ error.getCode()
+ "\nmessage: "
+ error.getMessage()
+ "\nData: "
+ error.getData();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.asfoundation.wallet.tokenswap;

import android.util.Log;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Bool;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.Uint;
import org.web3j.utils.Numeric;

public class SwapDataMapper {
public byte[] getDataSwapEtherToToken(SwapProof swapProof) {
Address destToken = new Address(swapProof.getDestToken());
Uint minConversionRate = new Uint(BigInteger.ZERO);
List<Type> params = Arrays.asList(destToken, minConversionRate);
List<TypeReference<?>> returnTypes = Collections.singletonList(new TypeReference<Bool>() {
});
Function function = new Function("swapEtherToToken", params, returnTypes);
String encodedFunction = FunctionEncoder.encode(function);
return Numeric.hexStringToByteArray(Numeric.cleanHexPrefix(encodedFunction));
}

public Function getDataExpectedRate(SwapProof swapProof) {
Address srcToken = new Address(swapProof.getSrcToken());
Address destToken = new Address(swapProof.getDestToken());
Uint srcQnty = new Uint(swapProof.getTokenAmount()
.toBigInteger());
List<Type> params = Arrays.asList(srcToken, destToken, srcQnty);
List<TypeReference<?>> returnTypes = Collections.singletonList(new TypeReference<Uint>() {
});
Function getRates = new Function("getExpectedRate", params, returnTypes);
return getRates;
}

public byte[] getDataApprove(SwapProof swapProof) {
String spender = swapProof.getToAddress();
BigDecimal amount = swapProof.getTokenAmount();
Log.d("swapLog2", "amount = " + String.valueOf(amount));
List<Type> params = Arrays.asList(new Address(spender), new Uint(amount.toBigInteger()));
List<TypeReference<?>> returnTypes = Collections.singletonList(new TypeReference<Bool>() {
});
Function function = new Function("approve", params, returnTypes);
String encodedFunction = FunctionEncoder.encode(function);
return Numeric.hexStringToByteArray(Numeric.cleanHexPrefix(encodedFunction));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.asfoundation.wallet.tokenswap;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.EditText;
import com.asf.wallet.R;
import dagger.android.AndroidInjection;
import javax.inject.Inject;

public class SwapEtherToTokenActivity extends AppCompatActivity implements SwapView {
@Inject SwapInteractor swapInteractor;
private EditText etSrcAmount;
private ResponseListener<String> showTxHash;
private SwapPresenter presenter;
private EditText amountFromView;
private EditText amountToView;

public static Intent newIntent(Context context) {
return new Intent(context, SwapEtherToTokenActivity.class);
}

@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_swap_ether_to_token);
AndroidInjection.inject(this);
presenter = new SwapPresenter(this, swapInteractor);

etSrcAmount = findViewById(R.id.etAmountFrom);
amountFromView = findViewById(R.id.etAmountFrom);
amountToView = findViewById(R.id.etAmountTo);

findViewById(R.id.bSwap).setOnClickListener(v -> clickedSwap());
findViewById(R.id.imgRates).setOnClickListener(v -> clickedGetRates());
showTxHash = new ResponseListener<String>() {
@Override public void onResponse(String txHash) {
runOnUiThread(new Runnable() {
@Override public void run() {

Log.d("swapLog2", "hey");
}
});
}

@Override public void onError(Throwable error) {
error.printStackTrace();
}
};
}

@Override public void clickedGetRates() {
String toAddress = getString(R.string.RopstenKyberNetworkProxy);
String srcToken = getString(R.string.RopstenEther);
String destToken = getString(R.string.RopstenAppCoins);
String tokenAmount = etSrcAmount.getText()
.toString();

presenter.getRates(toAddress, srcToken, destToken, tokenAmount);
}

@Override public void showRates(String rates) {
amountToView.setText(rates);
}

@Override public void clickedSwap() {
String srcToken = getString(R.string.RopstenEther);
String destToken = getString(R.string.RopstenAppCoins);
String amount = amountFromView.getText()
.toString();
String toAddress = getString(R.string.RopstenKyberNetworkProxy);

presenter.swapEtherToToken(srcToken, destToken, amount, toAddress, showTxHash);
}
}




Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.asfoundation.wallet.tokenswap;

import java.math.BigInteger;
import org.web3j.utils.Convert;

public class SwapInteractor {
private final SwapProofWriter swapBlockchainWriter;
private final SwapDataMapper swapDataMapper;
private SwapProofFactory swapProofFactory;

public SwapInteractor(SwapProofWriter swapBlockchainWriter, SwapDataMapper swapDataMapper) {
this.swapBlockchainWriter = swapBlockchainWriter;
this.swapDataMapper = swapDataMapper;
this.swapProofFactory = new SwapProofFactory();
}

public BigInteger getRates(String toAddress, String srcToken, String destToken,
String tokenAmount) {
SwapProof swapProof = swapProofFactory.createDefaultSwapProof();
swapProof.setToAddress(toAddress);
swapProof.setSrcToken(srcToken);
swapProof.setDestToken(destToken);
swapProof.setTokenAmount(Convert.toWei(tokenAmount, Convert.Unit.ETHER));

BigInteger rateWei = swapBlockchainWriter.writeGetterSwapProof(swapProof);
return rateWei;
}

public void swapEtherToToken(String srcToken, String destToken, String amount, String ToAddress,
ResponseListener listener) {
SwapProof swapProof = swapProofFactory.createDefaultSwapProof();

swapProof.setSrcToken(srcToken);
swapProof.setDestToken(destToken);
swapProof.setAmount(Convert.toWei(amount, Convert.Unit.ETHER));
swapProof.setToAddress(ToAddress);
swapProof.setData(swapDataMapper.getDataSwapEtherToToken(swapProof));

swapBlockchainWriter.setListener(listener);
swapBlockchainWriter.writeSwapProof(swapProof);
}
}
Loading