Created
October 30, 2021 15:48
-
-
Save kaxline/99918c139c9d53cbe8d59a288ae164e8 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
package io.re_public.android; | |
import com.facebook.react.bridge.ReactApplicationContext; | |
import com.facebook.react.bridge.ReactContextBaseJavaModule; | |
import com.facebook.react.bridge.ReactMethod; | |
import com.facebook.react.bridge.Callback; | |
import org.bouncycastle.jce.provider.BouncyCastleProvider; | |
import org.json.JSONObject; | |
import org.web3j.crypto.Keys; | |
import org.web3j.crypto.ECKeyPair; | |
import org.web3j.crypto.WalletUtils; | |
import org.web3j.exceptions.MessageDecodingException; | |
import org.web3j.utils.Numeric; | |
import java.io.File; | |
import java.math.BigInteger; | |
import java.security.Provider; | |
import java.security.SecureRandom; | |
import java.security.Security; | |
import android.Manifest; | |
import android.app.AppOpsManager; | |
import android.content.Context; | |
import android.content.pm.PackageManager; | |
import android.content.pm.ApplicationInfo; | |
public class EthereumWalletModule extends ReactContextBaseJavaModule { | |
private SecureRandom random = new SecureRandom(); | |
private Context mContext; | |
private void setupBouncyCastle() { | |
final Provider provider = Security.getProvider(BouncyCastleProvider.PROVIDER_NAME); | |
if (provider == null) { | |
// Web3j will set up the provider lazily when it's first used. | |
return; | |
} | |
if (provider.getClass().equals(BouncyCastleProvider.class)) { | |
// BC with same package name, shouldn't happen in real life. | |
return; | |
} | |
// Android registers its own BC provider. As it might be outdated and might not include | |
// all needed ciphers, we substitute it with a known BC bundled in the app. | |
// Android's BC has its package rewritten to "com.android.org.bouncycastle" and because | |
// of that it's possible to have another BC implementation loaded in VM. | |
Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME); | |
Security.insertProviderAt(new BouncyCastleProvider(), 1); | |
} | |
EthereumWalletModule(ReactApplicationContext context) { | |
super(context); | |
setupBouncyCastle(); | |
mContext = context; | |
} | |
private static JSONObject createEthereumAccount(String seed, String dataDir) { | |
JSONObject accountJson = new JSONObject(); | |
try { | |
File fileDir = new File(dataDir); | |
if (!fileDir.exists()) { | |
fileDir.mkdirs(); | |
} | |
ECKeyPair ecKeyPair = Keys.createEcKeyPair(); | |
String filename = WalletUtils.generateWalletFile(seed, ecKeyPair, fileDir, false); | |
String privateKeyHexString = Numeric.encodeQuantity(ecKeyPair.getPrivateKey()); | |
BigInteger decoded = Numeric.decodeQuantity(privateKeyHexString); | |
accountJson.put("filename", filename); | |
accountJson.put("privateKey", Numeric.encodeQuantity(ecKeyPair.getPrivateKey())); | |
accountJson.put("publicKey", Numeric.encodeQuantity(ecKeyPair.getPublicKey())); | |
} catch (MessageDecodingException e) { | |
return EthereumWalletModule.createEthereumAccount(seed, dataDir); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
return accountJson; | |
} | |
@Override | |
public String getName() { | |
return "EthereumWalletModule"; | |
} | |
@ReactMethod | |
public void hasPermissions(Callback callback) { | |
AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); | |
final int externalStorageMode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_WRITE_EXTERNAL_STORAGE, android.os.Process.myUid(), mContext.getPackageName()); | |
boolean granted = externalStorageMode == AppOpsManager.MODE_DEFAULT ? | |
(mContext.checkCallingOrSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) | |
: (externalStorageMode == AppOpsManager.MODE_ALLOWED); | |
callback.invoke(granted); | |
} | |
@ReactMethod | |
public void createEthereumWallet(Callback callback) { | |
ApplicationInfo appInfo = getCurrentActivity().getApplicationInfo(); | |
String dataDir = "no app info"; | |
if (appInfo != null) { | |
dataDir = appInfo.dataDir; | |
} | |
String seed = new BigInteger(130, random).toString(32); | |
JSONObject result = createEthereumAccount(seed, dataDir); | |
callback.invoke(result.toString()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment