Skip to content

Commit 0b918fe

Browse files
authored
Allow users to purchase assets via Coinbase Pay (#2781)
* Allow users to buy assets with Coinbase Pay * Remove unused methods/tests * Update test * Add router test * Move Coinbase Pay App ID to keys
1 parent bd1bc80 commit 0b918fe

38 files changed

+834
-96
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@ on:
66
pull_request:
77
jobs:
88
test:
9-
runs-on: macos-latest
9+
runs-on: self-hosted
1010
steps:
1111
- uses: actions/checkout@v3
12-
12+
1313
- name: Set up JDK
1414
uses: actions/setup-java@v3
1515
with:
1616
distribution: zulu
1717
java-version: 11
18-
cache: gradle
18+
architecture: arm64
1919

2020
- name: Run unit tests
2121
run: sh ./build.sh

app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ dependencies {
289289
testImplementation group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.9'
290290

291291
// Component tests
292-
testImplementation 'org.robolectric:robolectric:4.8.1'
292+
testImplementation 'org.robolectric:robolectric:4.8.2'
293293
testImplementation 'androidx.test:core:1.4.0'
294294
testImplementation 'androidx.test.ext:junit:1.1.3'
295295

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.alphawallet.app;
2+
3+
import static androidx.test.espresso.matcher.ViewMatchers.withId;
4+
import static androidx.test.espresso.matcher.ViewMatchers.withText;
5+
import static com.alphawallet.app.assertions.Should.shouldSee;
6+
import static com.alphawallet.app.steps.Steps.addNewNetwork;
7+
import static com.alphawallet.app.steps.Steps.assertBalanceIs;
8+
import static com.alphawallet.app.steps.Steps.createNewWallet;
9+
import static com.alphawallet.app.steps.Steps.ensureTransactionConfirmed;
10+
import static com.alphawallet.app.steps.Steps.getWalletAddress;
11+
import static com.alphawallet.app.steps.Steps.gotoSettingsPage;
12+
import static com.alphawallet.app.steps.Steps.importWalletFromSettingsPage;
13+
import static com.alphawallet.app.steps.Steps.selectTestNet;
14+
import static com.alphawallet.app.steps.Steps.sendBalanceTo;
15+
import static com.alphawallet.app.steps.Steps.switchToWallet;
16+
import static com.alphawallet.app.steps.Steps.toggleSwitch;
17+
import static com.alphawallet.app.util.Helper.click;
18+
import static org.hamcrest.CoreMatchers.equalTo;
19+
import static org.hamcrest.MatcherAssert.assertThat;
20+
import static org.junit.Assert.fail;
21+
22+
import android.os.Build;
23+
24+
import org.junit.Test;
25+
26+
import java.util.HashMap;
27+
import java.util.Map;
28+
29+
public class CoinbasePayTest extends BaseE2ETest {
30+
@Test
31+
public void should_see_coinbase_pay_window()
32+
{
33+
createNewWallet();
34+
click(withText("Buy ETH"));
35+
shouldSee("Buy with Coinbase Pay");
36+
click(withId(R.id.buy_with_coinbase_pay));
37+
shouldSee("Buy with Coinbase Pay");
38+
}
39+
}

app/src/main/AndroidManifest.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,10 @@
311311
android:name=".ui.NodeStatusActivity"
312312
android:label="@string/action_node_status" />
313313

314+
<activity
315+
android:name=".ui.CoinbasePayActivity"
316+
android:label="@string/title_buy_with_coinbase_pay" />
317+
314318
<activity
315319
android:name=".ui.WalletDiagnosticActivity"
316320
android:label="@string/key_diagnostic" />

app/src/main/cpp/keys.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,17 @@ Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getRampKey( JNIEnv* env,
6868
#endif
6969
}
7070

71+
JNIEXPORT jstring JNICALL
72+
Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getCoinbasePayAppId( JNIEnv* env, jobject thiz )
73+
{
74+
#if (HAS_KEYS == 1)
75+
return getDecryptedKey(env, coinbasePayAppId);
76+
#else
77+
const jstring key = ""; // <-- replace with your Coinbase Pay app id
78+
return (*env)->NewStringUTF(env, key);
79+
#endif
80+
}
81+
7182
JNIEXPORT jstring JNICALL
7283
Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getSecondaryInfuraKey( JNIEnv* env, jobject thiz )
7384
{

app/src/main/java/com/alphawallet/app/C.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ public enum TokenStatus {
299299
public static final String AN_USE_GAS = "Gas Settings";
300300
public static final String AN_CALL_ACTIONSHEET = "Use ActionSheet";
301301
public static final String AN_USE_ONRAMP = "Use OnRamp";
302+
public static final String AN_USE_COINBASE_PAY = "Use Coinbase Pay";
302303
public static final String APP_NAME = "PACKAGE_NAME";
303304

304305
public static final String ALPHAWALLET_LOGO_URI = "https://alphawallet.com/wp-content/themes/alphawallet/img/alphawallet-logo.svg";

app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
import android.content.Context;
66

7+
import com.alphawallet.app.repository.CoinbasePayRepository;
8+
import com.alphawallet.app.repository.CoinbasePayRepositoryType;
79
import com.alphawallet.app.repository.EthereumNetworkRepository;
810
import com.alphawallet.app.repository.EthereumNetworkRepositoryType;
911
import com.alphawallet.app.repository.OnRampRepository;
@@ -115,6 +117,12 @@ OnRampRepositoryType provideOnRampRepository(@ApplicationContext Context context
115117
return new OnRampRepository(context, analyticsServiceType);
116118
}
117119

120+
@Singleton
121+
@Provides
122+
CoinbasePayRepositoryType provideCoinbasePayRepository() {
123+
return new CoinbasePayRepository();
124+
}
125+
118126
@Singleton
119127
@Provides
120128
TransactionLocalSource provideTransactionInDiskCache(RealmManager realmManager) {

app/src/main/java/com/alphawallet/app/di/ViewModelModule.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.alphawallet.app.repository.TokenRepositoryType;
2323
import com.alphawallet.app.repository.TransactionRepositoryType;
2424
import com.alphawallet.app.repository.WalletRepositoryType;
25+
import com.alphawallet.app.router.CoinbasePayRouter;
2526
import com.alphawallet.app.router.ExternalBrowserRouter;
2627
import com.alphawallet.app.router.HomeRouter;
2728
import com.alphawallet.app.router.ImportTokenRouter;
@@ -98,6 +99,11 @@ MyAddressRouter provideMyAddressRouter() {
9899
return new MyAddressRouter();
99100
}
100101

102+
@Provides
103+
CoinbasePayRouter provideCoinbasePayRouter() {
104+
return new CoinbasePayRouter();
105+
}
106+
101107
@Provides
102108
FetchTokensInteract provideFetchTokensInteract(TokenRepositoryType tokenRepository) {
103109
return new FetchTokensInteract(tokenRepository);
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.alphawallet.app.entity.coinbasepay;
2+
3+
import java.util.List;
4+
5+
public class DestinationWallet
6+
{
7+
final transient Type type;
8+
String address;
9+
List<String> blockchains;
10+
List<String> assets;
11+
12+
public DestinationWallet(Type type, String address, List<String> list)
13+
{
14+
this.type = type;
15+
this.address = address;
16+
if (type.equals(Type.ASSETS))
17+
{
18+
this.assets = list;
19+
}
20+
else
21+
{
22+
this.blockchains = list;
23+
}
24+
}
25+
26+
public enum Type
27+
{
28+
ASSETS,
29+
BLOCKCHAINS
30+
}
31+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.alphawallet.app.repository;
2+
3+
import android.net.Uri;
4+
import android.text.TextUtils;
5+
6+
import com.alphawallet.app.entity.coinbasepay.DestinationWallet;
7+
import com.alphawallet.app.util.CoinbasePayUtils;
8+
9+
import java.util.List;
10+
11+
public class CoinbasePayRepository implements CoinbasePayRepositoryType
12+
{
13+
private static final String SCHEME = "https";
14+
private static final String AUTHORITY = "pay.coinbase.com";
15+
private static final String BUY_PATH = "buy";
16+
private static final String SELECT_ASSET_PATH = "select-asset";
17+
private final KeyProvider keyProvider = KeyProviderFactory.get();
18+
19+
@Override
20+
public String getUri(DestinationWallet.Type type, String address, List<String> list)
21+
{
22+
String appId = keyProvider.getCoinbasePayAppId();
23+
if (TextUtils.isEmpty(appId))
24+
{
25+
return "";
26+
}
27+
else
28+
{
29+
Uri.Builder builder = new Uri.Builder();
30+
builder.scheme(SCHEME)
31+
.authority(AUTHORITY)
32+
.appendPath(BUY_PATH)
33+
.appendPath(SELECT_ASSET_PATH)
34+
.appendQueryParameter(RequestParams.APP_ID, keyProvider.getCoinbasePayAppId())
35+
.appendQueryParameter(RequestParams.DESTINATION_WALLETS, CoinbasePayUtils.getDestWalletJson(type, address, list));
36+
37+
return builder.build().toString();
38+
}
39+
}
40+
41+
public static class Blockchains
42+
{
43+
public static final String ETHEREUM = "ethereum";
44+
public static final String SOLANA = "solana";
45+
public static final String AVALANCHE_C_CHAIN = "avalanche-c-chain";
46+
}
47+
48+
private static class RequestParams
49+
{
50+
public static final String APP_ID = "appId";
51+
public static final String ADDRESS = "address";
52+
public static final String DESTINATION_WALLETS = "destinationWallets";
53+
public static final String ASSETS = "assets";
54+
public static final String BLOCKCHAINS = "blockchains";
55+
}
56+
}

0 commit comments

Comments
 (0)