From 5622b1c50e0c44ebf6e805336e1fc3bbd56db75b Mon Sep 17 00:00:00 2001 From: Marco Martinez Date: Mon, 27 Nov 2023 14:33:19 -0700 Subject: [PATCH] MWA 2.0 Auth Repository (#605) * auth repo changes only * single account auth only with new auth repo * cleanup * remove debug print * fix db migration * cleanup * pr feedback - rename query * add comment --- .../MobileWalletAdapterViewModel.kt | 8 +- .../authorization/AccountRecord.java | 41 ++++++++ .../authorization/AccountRecordsDao.java | 99 +++++++++++++++++++ .../AccountRecordsDaoInterface.java | 19 ++++ .../authorization/AccountRecordsSchema.java | 29 ++++++ .../walletlib/authorization/AuthDatabase.java | 52 ++++++++-- .../walletlib/authorization/AuthRecord.java | 28 ++++-- .../authorization/AuthRepository.java | 12 +++ .../authorization/AuthRepositoryImpl.java | 63 ++++++++---- .../authorization/AuthorizationsDao.java | 59 ++++++----- .../AuthorizationsDaoInterface.java | 2 +- .../authorization/AuthorizationsSchema.java | 11 ++- .../walletlib/authorization/PublicKey.java | 2 + .../authorization/PublicKeysDao.java | 19 ++++ .../authorization/PublicKeysDaoInterface.java | 1 + .../authorization/PublicKeysSchema.java | 1 + .../protocol/MobileWalletAdapterServer.java | 47 +++++---- .../walletlib/scenario/AuthorizeRequest.java | 4 +- .../walletlib/scenario/LocalScenario.java | 14 ++- 19 files changed, 408 insertions(+), 103 deletions(-) create mode 100644 android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AccountRecord.java create mode 100644 android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AccountRecordsDao.java create mode 100644 android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AccountRecordsDaoInterface.java create mode 100644 android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AccountRecordsSchema.java diff --git a/android/fakewallet/src/main/java/com/solana/mobilewalletadapter/fakewallet/MobileWalletAdapterViewModel.kt b/android/fakewallet/src/main/java/com/solana/mobilewalletadapter/fakewallet/MobileWalletAdapterViewModel.kt index 63f28725..e70f5172 100644 --- a/android/fakewallet/src/main/java/com/solana/mobilewalletadapter/fakewallet/MobileWalletAdapterViewModel.kt +++ b/android/fakewallet/src/main/java/com/solana/mobilewalletadapter/fakewallet/MobileWalletAdapterViewModel.kt @@ -117,8 +117,8 @@ class MobileWalletAdapterViewModel(application: Application) : AndroidViewModel( val keypair = getApplication().keyRepository.generateKeypair() val publicKey = keypair.public as Ed25519PublicKeyParameters Log.d(TAG, "Generated a new keypair (pub=${publicKey.encoded.contentToString()}) for authorize request") - val accounts = arrayOf(buildAccount(publicKey.encoded, "fakewallet")) - request.request.completeWithAuthorize(accounts, null, + val account = buildAccount(publicKey.encoded, "fakewallet") + request.request.completeWithAuthorize(account, null, request.sourceVerificationState.authorizationScope.encodeToByteArray(), null) } else { request.request.completeWithDecline() @@ -174,8 +174,8 @@ class MobileWalletAdapterViewModel(application: Application) : AndroidViewModel( val signInResult = SignInResult(publicKey.encoded, siwsMessage.encodeToByteArray(), signResult.signature, "ed25519") - val accounts = arrayOf(buildAccount(publicKey.encoded, "fakewallet")) - request.request.completeWithAuthorize(accounts, null, + val account = buildAccount(publicKey.encoded, "fakewallet") + request.request.completeWithAuthorize(account, null, request.sourceVerificationState.authorizationScope.encodeToByteArray(), signInResult) } else { request.request.completeWithDecline() diff --git a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AccountRecord.java b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AccountRecord.java new file mode 100644 index 00000000..248ea92e --- /dev/null +++ b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AccountRecord.java @@ -0,0 +1,41 @@ +package com.solana.mobilewalletadapter.walletlib.authorization; + +import android.net.Uri; + +import androidx.annotation.IntRange; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +/* package */ class AccountRecord { + @IntRange(from = 1) + final int id; + + @NonNull + final byte[] publicKeyRaw; + + @Nullable + final String accountLabel; + + @Nullable + final Uri icon; + + @Nullable + final String[] chains; + + @Nullable + final String[] features; + + AccountRecord(@IntRange(from = 1) int id, + @NonNull byte[] publicKeyRaw, + @Nullable String accountLabel, + @Nullable Uri icon, + @Nullable String[] chains, + @Nullable String[] features) { + this.id = id; + this.publicKeyRaw = publicKeyRaw; + this.accountLabel = accountLabel; + this.icon = icon; + this.chains = chains; + this.features = features; + } +} diff --git a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AccountRecordsDao.java b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AccountRecordsDao.java new file mode 100644 index 00000000..9de6f363 --- /dev/null +++ b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AccountRecordsDao.java @@ -0,0 +1,99 @@ +package com.solana.mobilewalletadapter.walletlib.authorization; + +import android.content.ContentValues; +import android.database.Cursor; +import android.database.sqlite.SQLiteCursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteStatement; +import android.net.Uri; +import android.text.TextUtils; + +import androidx.annotation.IntRange; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +public class AccountRecordsDao extends DbContentProvider + implements AccountRecordsDaoInterface, AccountRecordsSchema { + + public AccountRecordsDao(SQLiteDatabase db) { super(db); } + + @NonNull + @Override + protected AccountRecord cursorToEntity(@NonNull Cursor cursor) { + final int publicKeyId = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_ACCOUNTS_ID)); + final byte[] publicKey = cursor.getBlob(cursor.getColumnIndexOrThrow(COLUMN_ACCOUNTS_PUBLIC_KEY_RAW)); + final String accountLabel = cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_ACCOUNTS_LABEL)); + final String accountIconStr = cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_ACCOUNTS_ICON)); + final String chainsString = cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_ACCOUNTS_CHAINS)); + final String featuresString = cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_ACCOUNTS_FEATURES)); + final Uri accountIcon = Uri.parse(accountIconStr); + final String[] chains = deserialize(chainsString); + final String[] features = deserialize(featuresString); + return new AccountRecord(publicKeyId, publicKey, accountLabel, accountIcon, chains, features); + } + + @Override + public long insert(@NonNull byte[] publicKey, + @Nullable String accountLabel, + @Nullable Uri accountIcon, + @Nullable String[] chains, + @Nullable String[] features) { + final ContentValues accountContentValues = new ContentValues(4); + accountContentValues.put(COLUMN_ACCOUNTS_PUBLIC_KEY_RAW, publicKey); + accountContentValues.put(COLUMN_ACCOUNTS_LABEL, accountLabel); + accountContentValues.put(COLUMN_ACCOUNTS_ICON, accountIcon != null ? accountIcon.toString() : null); + accountContentValues.put(COLUMN_ACCOUNTS_CHAINS, chains != null ? serialize(chains) : null); + accountContentValues.put(COLUMN_ACCOUNTS_FEATURES, features != null ? serialize(features) : null); + return super.insert(TABLE_ACCOUNTS, accountContentValues); + } + + @Nullable + @Override + public AccountRecord query(@NonNull byte[] publicKey) { + final SQLiteDatabase.CursorFactory accountCursorFactory = (db1, masterQuery, editTable, query) -> { + query.bindBlob(1, publicKey); + return new SQLiteCursor(masterQuery, editTable, query); + }; + try (final Cursor cursor = super.queryWithFactory(accountCursorFactory, + TABLE_ACCOUNTS, + ACCOUNTS_COLUMNS, + COLUMN_ACCOUNTS_PUBLIC_KEY_RAW + "=?", + null)) { + if (!cursor.moveToNext()) { + return null; + } + return cursorToEntity(cursor); + } + } + + @Override + public void deleteUnreferencedAccounts() { + final SQLiteStatement deleteUnreferencedAccounts = super.compileStatement( + "DELETE FROM " + TABLE_ACCOUNTS + + " WHERE " + COLUMN_ACCOUNTS_ID + " NOT IN " + + "(SELECT DISTINCT " + AuthorizationsSchema.COLUMN_AUTHORIZATIONS_ACCOUNT_ID + + " FROM " + AuthorizationsSchema.TABLE_AUTHORIZATIONS + ')'); + deleteUnreferencedAccounts.executeUpdateDelete(); + } + + // using a long alphanumeric divider reduces the chance of an array element matching the divider + private static final String ARRAY_DIVIDER = "#a1r2ra5yd2iv1i9der"; + + private String serialize(String[] content){ return TextUtils.join(ARRAY_DIVIDER, content); } + + private static String[] deserialize(String content){ + return content.split(ARRAY_DIVIDER); + } + + /*package*/ static AccountRecord buildAccountRecordFromRaw(@IntRange(from = 1) int id, + @NonNull byte[] publicKeyRaw, + @Nullable String accountLabel, + @Nullable String iconStr, + @Nullable String chainsStr, + @Nullable String featuresStr) { + final Uri icon = iconStr != null ? Uri.parse(iconStr) : null; + final String[] chains = chainsStr != null ? deserialize(chainsStr) : null; + final String[] features = featuresStr != null ? deserialize(featuresStr) : null; + return new AccountRecord(id, publicKeyRaw, accountLabel, icon, chains, features); + } +} diff --git a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AccountRecordsDaoInterface.java b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AccountRecordsDaoInterface.java new file mode 100644 index 00000000..fcc0b48e --- /dev/null +++ b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AccountRecordsDaoInterface.java @@ -0,0 +1,19 @@ +package com.solana.mobilewalletadapter.walletlib.authorization; + +import android.net.Uri; + +import androidx.annotation.IntRange; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +/*package*/ interface AccountRecordsDaoInterface { + + @IntRange(from = -1) + long insert(@NonNull byte[] publicKey, @Nullable String accountLabel, @Nullable Uri accountIcon, + @Nullable String[] chains, @Nullable String[] features); + + @Nullable + AccountRecord query(@NonNull byte[] publicKey); + + void deleteUnreferencedAccounts(); +} diff --git a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AccountRecordsSchema.java b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AccountRecordsSchema.java new file mode 100644 index 00000000..870bb18b --- /dev/null +++ b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AccountRecordsSchema.java @@ -0,0 +1,29 @@ +package com.solana.mobilewalletadapter.walletlib.authorization; + +/*package*/ interface AccountRecordsSchema { + String TABLE_ACCOUNTS = "accounts"; + String COLUMN_ACCOUNTS_ID = "id"; // type: long + String COLUMN_ACCOUNTS_PUBLIC_KEY_RAW = "public_key_raw"; // type: byte[] + String COLUMN_ACCOUNTS_LABEL = "label"; // type: String + String COLUMN_ACCOUNTS_ICON = "icon"; // type: String + String COLUMN_ACCOUNTS_CHAINS = "chains"; // type: String + String COLUMN_ACCOUNTS_FEATURES = "features"; // type: String + + String CREATE_TABLE_ACCOUNTS = + "CREATE TABLE " + TABLE_ACCOUNTS + " (" + + COLUMN_ACCOUNTS_ID + " INTEGER NOT NULL PRIMARY KEY," + + COLUMN_ACCOUNTS_PUBLIC_KEY_RAW + " BLOB NOT NULL," + + COLUMN_ACCOUNTS_LABEL + " TEXT," + + COLUMN_ACCOUNTS_ICON + " TEXT," + + COLUMN_ACCOUNTS_CHAINS + " TEXT," + + COLUMN_ACCOUNTS_FEATURES + " TEXT)"; + + String[] ACCOUNTS_COLUMNS = new String[]{ + COLUMN_ACCOUNTS_ID, + COLUMN_ACCOUNTS_PUBLIC_KEY_RAW, + COLUMN_ACCOUNTS_LABEL, + COLUMN_ACCOUNTS_ICON, + COLUMN_ACCOUNTS_CHAINS, + COLUMN_ACCOUNTS_FEATURES + }; +} diff --git a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthDatabase.java b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthDatabase.java index 51b2bab8..b3eae9f8 100644 --- a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthDatabase.java +++ b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthDatabase.java @@ -11,10 +11,12 @@ import androidx.annotation.NonNull; +import java.util.List; + /*package*/ class AuthDatabase extends SQLiteOpenHelper { private static final String TAG = AuthDatabase.class.getSimpleName(); private static final String DATABASE_NAME_SUFFIX = "-solana-wallet-lib-auth.db"; - private static final int DATABASE_SCHEMA_VERSION = 5; + private static final int DATABASE_SCHEMA_VERSION = 6; AuthDatabase(@NonNull Context context, @NonNull AuthIssuerConfig authIssuerConfig) { super(context, getDatabaseName(authIssuerConfig), null, DATABASE_SCHEMA_VERSION); @@ -29,18 +31,52 @@ public void onConfigure(SQLiteDatabase db) { public void onCreate(SQLiteDatabase db) { db.execSQL(IdentityRecordSchema.CREATE_TABLE_IDENTITIES); db.execSQL(AuthorizationsSchema.CREATE_TABLE_AUTHORIZATIONS); - db.execSQL(PublicKeysSchema.CREATE_TABLE_PUBLIC_KEYS); + db.execSQL(AccountRecordsSchema.CREATE_TABLE_ACCOUNTS); db.execSQL(WalletUriBaseSchema.CREATE_TABLE_WALLET_URI_BASE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - Log.w(TAG, "Old database schema detected; pre-v1.0.0, no DB schema backward compatibility is implemented"); - db.execSQL("DROP TABLE IF EXISTS " + IdentityRecordSchema.TABLE_IDENTITIES); - db.execSQL("DROP TABLE IF EXISTS " + AuthorizationsSchema.TABLE_AUTHORIZATIONS); - db.execSQL("DROP TABLE IF EXISTS " + PublicKeysSchema.TABLE_PUBLIC_KEYS); - db.execSQL("DROP TABLE IF EXISTS " + WalletUriBaseSchema.TABLE_WALLET_URI_BASE); - onCreate(db); + if (oldVersion < 5) { + Log.w(TAG, "Old database schema detected; pre-v1.0.0, no DB schema backward compatibility is implemented"); + db.execSQL("DROP TABLE IF EXISTS " + IdentityRecordSchema.TABLE_IDENTITIES); + db.execSQL("DROP TABLE IF EXISTS " + AuthorizationsSchema.TABLE_AUTHORIZATIONS); + db.execSQL("DROP TABLE IF EXISTS " + PublicKeysSchema.TABLE_PUBLIC_KEYS); + db.execSQL("DROP TABLE IF EXISTS " + WalletUriBaseSchema.TABLE_WALLET_URI_BASE); + onCreate(db); + } else { + Log.w(TAG, "Old database schema detected; pre-v2.0.0, migrating public keys to account records"); + final PublicKeysDao publicKeysDao = new PublicKeysDao(db); + publicKeysDao.deleteUnreferencedPublicKeys(); + + db.execSQL(AccountRecordsSchema.CREATE_TABLE_ACCOUNTS); + db.execSQL("ALTER TABLE " + AuthorizationsSchema.TABLE_AUTHORIZATIONS + + " RENAME COLUMN " + AuthorizationsSchema.COLUMN_AUTHORIZATIONS_PUBLIC_KEY_ID + + " TO " + AuthorizationsSchema.COLUMN_AUTHORIZATIONS_ACCOUNT_ID); + db.execSQL("ALTER TABLE " + AuthorizationsSchema.TABLE_AUTHORIZATIONS + + " RENAME COLUMN " + AuthorizationsSchema.COLUMN_AUTHORIZATIONS_CLUSTER + + " TO " + AuthorizationsSchema.COLUMN_AUTHORIZATIONS_CHAIN); + + final List publicKeys = publicKeysDao.getPublicKeys(); + if (!publicKeys.isEmpty()) { + AccountRecordsDao accountRecordsDao = new AccountRecordsDao(db); + for (PublicKey publicKey : publicKeys) { + final long accountId = accountRecordsDao.insert(publicKey.publicKeyRaw, + publicKey.accountLabel, null, null, null); + + // the public keys will be sorted by their id, and the new account ID will + // always be >= the existing public key ID so it is safe to update these values + // in place. For publicKey.id p(n) and accountId a(n), p(n) > p(n-1) and + // a(n) >= p(n), therefore a(n) > p(n-1). So the 'WHERE account_id = p(n)' + // condition here will not collide with previously updated entries. + db.execSQL("UPDATE " + AuthorizationsSchema.TABLE_AUTHORIZATIONS + + " SET " + AuthorizationsSchema.COLUMN_AUTHORIZATIONS_ACCOUNT_ID + " = " + accountId + + " WHERE " + AuthorizationsSchema.COLUMN_AUTHORIZATIONS_ACCOUNT_ID + " = " + publicKey.id); + } + } + + db.execSQL("DROP TABLE IF EXISTS " + PublicKeysSchema.TABLE_PUBLIC_KEYS); + } } @NonNull diff --git a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthRecord.java b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthRecord.java index 5ac9be0d..e8d7f01f 100644 --- a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthRecord.java +++ b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthRecord.java @@ -10,6 +10,8 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.solana.mobilewalletadapter.walletlib.scenario.AuthorizedAccount; + import java.util.Arrays; import java.util.Objects; @@ -32,10 +34,14 @@ public class AuthRecord { @Nullable public final String accountLabel; + @NonNull + public final AccountRecord accountRecord; + @NonNull public final String chain; - @NonNull @Deprecated + @Deprecated + @NonNull public final String cluster; @NonNull @@ -45,7 +51,7 @@ public class AuthRecord { public final Uri walletUriBase; @IntRange(from = 1) - /*package*/ final int publicKeyId; + /*package*/ final int accountId; @IntRange(from = 1) /*package*/ final int walletUriBaseId; @@ -54,12 +60,11 @@ public class AuthRecord { /*package*/ AuthRecord(@IntRange(from = 1) int id, @NonNull IdentityRecord identity, - @NonNull byte[] publicKey, - @Nullable String accountLabel, + @NonNull AccountRecord accountRecord, @NonNull String chain, @NonNull byte[] scope, @Nullable Uri walletUriBase, - @IntRange(from = 1) int publicKeyId, + @IntRange(from = 1) int accountId, @IntRange(from = 1) int walletUriBaseId, @IntRange(from = 0) long issued, @IntRange(from = 0) long expires) { @@ -67,16 +72,23 @@ public class AuthRecord { // other components within this package. this.id = id; this.identity = identity; - this.publicKey = publicKey; - this.accountLabel = accountLabel; + this.accountRecord = accountRecord; this.chain = chain; this.cluster = chain; this.scope = scope; this.walletUriBase = walletUriBase; - this.publicKeyId = publicKeyId; + this.accountId = accountId; this.walletUriBaseId = walletUriBaseId; this.issued = issued; this.expires = expires; + + this.publicKey = accountRecord.publicKeyRaw; + this.accountLabel = accountRecord.accountLabel; + } + + public AuthorizedAccount authorizedAccount() { + return new AuthorizedAccount(accountRecord.publicKeyRaw, accountRecord.accountLabel, + accountRecord.icon, accountRecord.chains, accountRecord.features); } public boolean isExpired() { diff --git a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthRepository.java b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthRepository.java index 1fc5e266..10738067 100644 --- a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthRepository.java +++ b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthRepository.java @@ -5,6 +5,8 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.solana.mobilewalletadapter.walletlib.scenario.AuthorizedAccount; + import java.util.List; public interface AuthRepository { @@ -19,6 +21,7 @@ public interface AuthRepository { @NonNull String toAuthToken(@NonNull AuthRecord authRecord); + @Deprecated @NonNull AuthRecord issue(@NonNull String name, @NonNull Uri uri, @@ -29,6 +32,15 @@ AuthRecord issue(@NonNull String name, @Nullable Uri walletUriBase, @Nullable byte[] scope); + @NonNull + AuthRecord issue(@NonNull String name, + @NonNull Uri uri, + @NonNull Uri relativeIconUri, + @NonNull AuthorizedAccount account, + @NonNull String cluster, + @Nullable Uri walletUriBase, + @Nullable byte[] scope); + @Nullable AuthRecord reissue(@NonNull AuthRecord authRecord); diff --git a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthRepositoryImpl.java b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthRepositoryImpl.java index be4ad773..bc1a8032 100644 --- a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthRepositoryImpl.java +++ b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthRepositoryImpl.java @@ -18,6 +18,8 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.solana.mobilewalletadapter.walletlib.scenario.AuthorizedAccount; + import org.json.JSONException; import org.json.JSONObject; @@ -69,7 +71,9 @@ public class AuthRepositoryImpl implements AuthRepository { private IdentityRecordDao mIdentityRecordDao; private AuthorizationsDao mAuthorizationsDao; private WalletUriBaseDao mWalletUriBaseDao; + @Deprecated private PublicKeysDao mPublicKeysDao; + private AccountRecordsDao mAccountsDao; public AuthRepositoryImpl(@NonNull Context context, @NonNull AuthIssuerConfig authIssuerConfig) { mContext = context; @@ -105,6 +109,7 @@ private void ensureStarted() { mAuthorizationsDao = new AuthorizationsDao(database, mAuthIssuerConfig); mWalletUriBaseDao = new WalletUriBaseDao(database); mPublicKeysDao = new PublicKeysDao(database); + mAccountsDao = new AccountRecordsDao(database); mInitialized = true; } } @@ -293,6 +298,7 @@ private boolean revokeNonReissuableAuthRecord(@NonNull AuthRecord authRecord) { return revoke; } + @Deprecated @NonNull @Override public synchronized AuthRecord issue(@NonNull String name, @@ -303,6 +309,20 @@ public synchronized AuthRecord issue(@NonNull String name, @NonNull String cluster, @Nullable Uri walletUriBase, @Nullable byte[] scope) { + return issue(name, uri, relativeIconUri, + new AuthorizedAccount(publicKey, accountLabel, null, null, null), + cluster, walletUriBase, scope); + } + + @NonNull + @Override + public AuthRecord issue(@NonNull String name, + @NonNull Uri uri, + @NonNull Uri relativeIconUri, + @NonNull AuthorizedAccount account, + @NonNull String cluster, + @Nullable Uri walletUriBase, + @Nullable byte[] scope) { ensureStarted(); if (scope == null) { @@ -343,15 +363,18 @@ public synchronized AuthRecord issue(@NonNull String name, } - // Next, try and look up the public key - final PublicKey pk = mPublicKeysDao.query(publicKey); + // Next, try and look up the account + final AccountRecord accountRecordQueried = mAccountsDao.query(account.publicKey); - final int publicKeyId; - // If no matching public key exists, create one - if (pk == null) { - publicKeyId = (int) mPublicKeysDao.insert(publicKey, accountLabel); + final int accountId; + final AccountRecord accountRecord; + // If no matching account exists, create one + if (accountRecordQueried == null) { + accountId = (int) mAccountsDao.insert(account.publicKey, account.accountLabel, account.icon, account.chains, account.features); + accountRecord = new AccountRecord(accountId, account.publicKey, account.accountLabel, account.icon, account.chains, account.features); } else { - publicKeyId = pk.id; + accountId = accountRecordQueried.id; + accountRecord = accountRecordQueried; } // Next, try and look up the wallet URI base @@ -367,7 +390,7 @@ public synchronized AuthRecord issue(@NonNull String name, final long now = System.currentTimeMillis(); - final int id = (int) mAuthorizationsDao.insert(identityRecord.getId(), now, publicKeyId, cluster, walletUriBaseId, scope); + final int id = (int) mAuthorizationsDao.insert(identityRecord.getId(), now, accountId, cluster, walletUriBaseId, scope); // If needed, purge oldest entries for this identity final int purgeCount = mAuthorizationsDao.purgeOldestEntries(identityRecord.getId()); @@ -375,12 +398,12 @@ public synchronized AuthRecord issue(@NonNull String name, Log.v(TAG, "Purged " + purgeCount + " oldest authorizations for identity: " + identityRecord); // Note: we only purge if we exceeded the max outstanding authorizations per identity. We // thus know that the identity remains referenced; no need to purge unused identities. - deleteUnreferencedPublicKeys(); + deleteUnreferencedAccounts(); deleteUnreferencedWalletUriBase(); } - return new AuthRecord(id, identityRecord, publicKey, accountLabel, cluster, scope, - walletUriBase, publicKeyId, walletUriBaseId, now, + return new AuthRecord(id, identityRecord, accountRecord, cluster, scope, + walletUriBase, accountId, walletUriBaseId, now, now + mAuthIssuerConfig.authorizationValidityMs); } @@ -403,11 +426,11 @@ public synchronized AuthRecord reissue(@NonNull AuthRecord authRecord) { reissued = authRecord; } else { final int id = (int) mAuthorizationsDao.insert(authRecord.identity.getId(), now, - authRecord.publicKeyId, authRecord.cluster, authRecord.walletUriBaseId, authRecord.scope); - reissued = new AuthRecord(id, authRecord.identity, authRecord.publicKey, - authRecord.accountLabel, authRecord.cluster, authRecord.scope, - authRecord.walletUriBase, authRecord.publicKeyId, authRecord.walletUriBaseId, - now, now + mAuthIssuerConfig.authorizationValidityMs); + authRecord.accountId, authRecord.chain, authRecord.walletUriBaseId, authRecord.scope); + reissued = new AuthRecord(id, authRecord.identity, authRecord.accountRecord, + authRecord.chain, authRecord.scope, authRecord.walletUriBase, + authRecord.accountId, authRecord.walletUriBaseId, now, + now + mAuthIssuerConfig.authorizationValidityMs); Log.d(TAG, "Reissued AuthRecord: " + reissued); revoke(authRecord); // Note: reissue is net-neutral on the number of authorizations per identity, so there's @@ -428,7 +451,7 @@ public synchronized boolean revoke(@NonNull AuthRecord authRecord) { // There may now be unreferenced authorization data; if so, delete them deleteUnreferencedIdentities(); - deleteUnreferencedPublicKeys(); + deleteUnreferencedAccounts(); deleteUnreferencedWalletUriBase(); return (deleteCount != 0); @@ -444,7 +467,7 @@ public synchronized boolean revoke(@NonNull IdentityRecord identityRecord) { final int deleteCount = mIdentityRecordDao.deleteById(identityRecord.getId()); // There may now be unreferenced authorization data; if so, delete them - deleteUnreferencedPublicKeys(); + deleteUnreferencedAccounts(); deleteUnreferencedWalletUriBase(); return (deleteCount != 0); @@ -456,8 +479,8 @@ private void deleteUnreferencedIdentities() { } @GuardedBy("this") - private void deleteUnreferencedPublicKeys() { - mPublicKeysDao.deleteUnreferencedPublicKeys(); + private void deleteUnreferencedAccounts() { + mAccountsDao.deleteUnreferencedAccounts(); } @GuardedBy("this") diff --git a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthorizationsDao.java b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthorizationsDao.java index 14c555d1..42184269 100644 --- a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthorizationsDao.java +++ b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthorizationsDao.java @@ -18,7 +18,7 @@ import java.util.List; /*package*/ class AuthorizationsDao extends DbContentProvider - implements AuthorizationsSchema, PublicKeysSchema, + implements AuthorizationsSchema, AccountRecordsSchema, WalletUriBaseSchema, AuthorizationsDaoInterface { @NonNull @@ -39,26 +39,30 @@ protected AuthRecord cursorToEntity(@NonNull Cursor cursor) { private AuthRecord cursorToEntity(@NonNull Cursor cursor, @NonNull IdentityRecord identityRecord) { final int id = cursor.getInt(0); final long issued = cursor.getLong(1); - final int publicKeyId = cursor.getInt(2); + final int accountId = cursor.getInt(2); final int walletUriBaseId = cursor.getInt(3); final byte[] scope = cursor.getBlob(4); final String cluster = cursor.getString(5); final byte[] publicKey = cursor.getBlob(6); final String accountLabel = cursor.isNull(7) ? null : cursor.getString(7); - final Uri walletUriBase = cursor.isNull(8) ? null : Uri.parse(cursor.getString(8)); - return new AuthRecord(id, identityRecord, publicKey, - accountLabel, cluster, scope, walletUriBase, publicKeyId, walletUriBaseId, - issued, issued + authIssuerConfig.authorizationValidityMs); + final String accountIconStr = cursor.isNull(8) ? null : cursor.getString(8); + final String chainsStr = cursor.isNull(9) ? null : cursor.getString(9); + final String featuresStr = cursor.isNull(10) ? null : cursor.getString(10); + final Uri walletUriBase = cursor.isNull(11) ? null : Uri.parse(cursor.getString(11)); + final AccountRecord account = AccountRecordsDao.buildAccountRecordFromRaw(accountId, + publicKey, accountLabel, accountIconStr, chainsStr, featuresStr); + return new AuthRecord(id, identityRecord, account, cluster, scope, walletUriBase, accountId, + walletUriBaseId, issued, issued + authIssuerConfig.authorizationValidityMs); } @IntRange(from = -1) @Override - public long insert(@IntRange(from = 1) int id, long timeStamp, @IntRange(from = 1) int publicKeyId, @NonNull String cluster, @IntRange(from = 1) int walletUriBaseId, @Nullable byte[] scope) { + public long insert(@IntRange(from = 1) int id, long timeStamp, @IntRange(from = 1) int accountId, @NonNull String cluster, @IntRange(from = 1) int walletUriBaseId, @Nullable byte[] scope) { final ContentValues contentValues = new ContentValues(6); contentValues.put(COLUMN_AUTHORIZATIONS_IDENTITY_ID, id); contentValues.put(COLUMN_AUTHORIZATIONS_ISSUED, timeStamp); - contentValues.put(COLUMN_AUTHORIZATIONS_PUBLIC_KEY_ID, publicKeyId); - contentValues.put(COLUMN_AUTHORIZATIONS_CLUSTER, cluster); + contentValues.put(COLUMN_AUTHORIZATIONS_ACCOUNT_ID, accountId); + contentValues.put(COLUMN_AUTHORIZATIONS_CHAIN, cluster); contentValues.put(COLUMN_AUTHORIZATIONS_WALLET_URI_BASE_ID, walletUriBaseId); contentValues.put(COLUMN_AUTHORIZATIONS_SCOPE, scope); return super.insert(TABLE_AUTHORIZATIONS, contentValues); @@ -89,17 +93,20 @@ public synchronized List getAuthorizations(@NonNull IdentityRecord i try (final Cursor cursor = super.rawQuery("SELECT " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_ID + ", " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_ISSUED + - ", " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_PUBLIC_KEY_ID + + ", " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_ACCOUNT_ID + ", " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_WALLET_URI_BASE_ID + ", " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_SCOPE + - ", " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_CLUSTER + - ", " + TABLE_PUBLIC_KEYS + '.' + COLUMN_PUBLIC_KEYS_RAW + - ", " + TABLE_PUBLIC_KEYS + '.' + COLUMN_PUBLIC_KEYS_LABEL + + ", " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_CHAIN + + ", " + TABLE_ACCOUNTS + '.' + COLUMN_ACCOUNTS_PUBLIC_KEY_RAW + + ", " + TABLE_ACCOUNTS + '.' + COLUMN_ACCOUNTS_LABEL + + ", " + TABLE_ACCOUNTS + '.' + COLUMN_ACCOUNTS_ICON + + ", " + TABLE_ACCOUNTS + '.' + COLUMN_ACCOUNTS_CHAINS + + ", " + TABLE_ACCOUNTS + '.' + COLUMN_ACCOUNTS_FEATURES + ", " + TABLE_WALLET_URI_BASE + '.' + COLUMN_WALLET_URI_BASE_URI + " FROM " + TABLE_AUTHORIZATIONS + - " INNER JOIN " + TABLE_PUBLIC_KEYS + - " ON " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_PUBLIC_KEY_ID + - " = " + TABLE_PUBLIC_KEYS + '.' + COLUMN_PUBLIC_KEYS_ID + + " INNER JOIN " + TABLE_ACCOUNTS + + " ON " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_ACCOUNT_ID + + " = " + TABLE_ACCOUNTS + '.' + COLUMN_ACCOUNTS_ID + " INNER JOIN " + TABLE_WALLET_URI_BASE + " ON " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_WALLET_URI_BASE_ID + " = " + TABLE_WALLET_URI_BASE + '.' + COLUMN_WALLET_URI_BASE_ID + @@ -114,21 +121,25 @@ public synchronized List getAuthorizations(@NonNull IdentityRecord i @Nullable @Override - public AuthRecord getAuthorization(@NonNull IdentityRecord identityRecord, @NonNull String tokenIdStr) { + public AuthRecord getAuthorization(@NonNull IdentityRecord identityRecord, + @NonNull String tokenIdStr) { try (final Cursor cursor = super.rawQuery("SELECT " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_ID + ", " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_ISSUED + - ", " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_PUBLIC_KEY_ID + + ", " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_ACCOUNT_ID + ", " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_WALLET_URI_BASE_ID + ", " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_SCOPE + - ", " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_CLUSTER + - ", " + TABLE_PUBLIC_KEYS + '.' + COLUMN_PUBLIC_KEYS_RAW + - ", " + TABLE_PUBLIC_KEYS + '.' + COLUMN_PUBLIC_KEYS_LABEL + + ", " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_CHAIN + + ", " + TABLE_ACCOUNTS + '.' + COLUMN_ACCOUNTS_PUBLIC_KEY_RAW + + ", " + TABLE_ACCOUNTS + '.' + COLUMN_ACCOUNTS_LABEL + + ", " + TABLE_ACCOUNTS + '.' + COLUMN_ACCOUNTS_ICON + + ", " + TABLE_ACCOUNTS + '.' + COLUMN_ACCOUNTS_CHAINS + + ", " + TABLE_ACCOUNTS + '.' + COLUMN_ACCOUNTS_FEATURES + ", " + TABLE_WALLET_URI_BASE + '.' + COLUMN_WALLET_URI_BASE_URI + " FROM " + TABLE_AUTHORIZATIONS + - " INNER JOIN " + TABLE_PUBLIC_KEYS + - " ON " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_PUBLIC_KEY_ID + - " = " + TABLE_PUBLIC_KEYS + '.' + COLUMN_PUBLIC_KEYS_ID + + " INNER JOIN " + TABLE_ACCOUNTS + + " ON " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_ACCOUNT_ID + + " = " + TABLE_ACCOUNTS + '.' + COLUMN_ACCOUNTS_ID + " INNER JOIN " + TABLE_WALLET_URI_BASE + " ON " + TABLE_AUTHORIZATIONS + '.' + COLUMN_AUTHORIZATIONS_WALLET_URI_BASE_ID + " = " + TABLE_WALLET_URI_BASE + '.' + COLUMN_WALLET_URI_BASE_ID + diff --git a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthorizationsDaoInterface.java b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthorizationsDaoInterface.java index 6f9e60c7..cd48285b 100644 --- a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthorizationsDaoInterface.java +++ b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthorizationsDaoInterface.java @@ -13,7 +13,7 @@ /*package*/ interface AuthorizationsDaoInterface { @IntRange(from = -1) - long insert(@IntRange(from = 1) int id, long timeStamp, @IntRange(from = 1) int publicKeyId, @NonNull String cluster, @IntRange(from = 1) int walletUriBaseId, @Nullable byte[] scope); + long insert(@IntRange(from = 1) int id, long timeStamp, @IntRange(from = 1) int accountId, @NonNull String cluster, @IntRange(from = 1) int walletUriBaseId, @Nullable byte[] scope); @IntRange(from = 0) int deleteByAuthRecordId(@IntRange(from = 1) int authRecordId); diff --git a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthorizationsSchema.java b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthorizationsSchema.java index 20e9900a..b7da751f 100644 --- a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthorizationsSchema.java +++ b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/AuthorizationsSchema.java @@ -9,9 +9,14 @@ String COLUMN_AUTHORIZATIONS_ID = "id"; // type: int String COLUMN_AUTHORIZATIONS_IDENTITY_ID = "identity_id"; // type: long String COLUMN_AUTHORIZATIONS_ISSUED = "issued"; // type: long - String COLUMN_AUTHORIZATIONS_PUBLIC_KEY_ID = "public_key_id"; // type: long + String COLUMN_AUTHORIZATIONS_ACCOUNT_ID = "account_id"; // type: long String COLUMN_AUTHORIZATIONS_WALLET_URI_BASE_ID = "wallet_uri_base_id"; // type: long String COLUMN_AUTHORIZATIONS_SCOPE = "scope"; // type: byte[] + String COLUMN_AUTHORIZATIONS_CHAIN = "chain"; // type: String + + @Deprecated + String COLUMN_AUTHORIZATIONS_PUBLIC_KEY_ID = "public_key_id"; // type: long + @Deprecated String COLUMN_AUTHORIZATIONS_CLUSTER = "cluster"; // type: String String CREATE_TABLE_AUTHORIZATIONS = @@ -19,8 +24,8 @@ COLUMN_AUTHORIZATIONS_ID + " INTEGER NOT NULL PRIMARY KEY," + COLUMN_AUTHORIZATIONS_IDENTITY_ID + " INTEGER NOT NULL," + COLUMN_AUTHORIZATIONS_ISSUED + " INTEGER NOT NULL," + - COLUMN_AUTHORIZATIONS_PUBLIC_KEY_ID + " INTEGER NOT NULL," + + COLUMN_AUTHORIZATIONS_ACCOUNT_ID + " INTEGER NOT NULL," + COLUMN_AUTHORIZATIONS_WALLET_URI_BASE_ID + " INTEGER NOT NULL," + COLUMN_AUTHORIZATIONS_SCOPE + " BLOB NOT NULL," + - COLUMN_AUTHORIZATIONS_CLUSTER + " TEXT NOT NULL)"; + COLUMN_AUTHORIZATIONS_CHAIN + " TEXT NOT NULL)"; } diff --git a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/PublicKey.java b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/PublicKey.java index 4b399806..7aab7c12 100644 --- a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/PublicKey.java +++ b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/PublicKey.java @@ -8,6 +8,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +@Deprecated /*package*/ class PublicKey { @IntRange(from = 1) final int id; @@ -18,6 +19,7 @@ @Nullable final String accountLabel; + @Deprecated PublicKey(@IntRange(from = 1) int id, @NonNull byte[] publicKeyRaw, @Nullable String accountLabel) { this.id = id; this.publicKeyRaw = publicKeyRaw; diff --git a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/PublicKeysDao.java b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/PublicKeysDao.java index d92986b8..45f226b8 100644 --- a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/PublicKeysDao.java +++ b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/PublicKeysDao.java @@ -14,6 +14,10 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; + +@Deprecated public class PublicKeysDao extends DbContentProvider implements PublicKeysDaoInterface, PublicKeysSchema { PublicKeysDao(SQLiteDatabase db) { @@ -66,4 +70,19 @@ public void deleteUnreferencedPublicKeys() { " FROM " + AuthorizationsSchema.TABLE_AUTHORIZATIONS + ')'); deleteUnreferencedPublicKeys.executeUpdateDelete(); } + + @NonNull + /*package*/ List getPublicKeys() { + final ArrayList publicKeys = new ArrayList<>(); + try (final Cursor c = super.query(TABLE_PUBLIC_KEYS, + PUBLIC_KEYS_COLUMNS, + null, + null, + COLUMN_PUBLIC_KEYS_ID)) { + while (c.moveToNext()) { + publicKeys.add(cursorToEntity(c)); + } + } + return publicKeys; + } } diff --git a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/PublicKeysDaoInterface.java b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/PublicKeysDaoInterface.java index 5a88e3cc..c4e96c03 100644 --- a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/PublicKeysDaoInterface.java +++ b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/PublicKeysDaoInterface.java @@ -8,6 +8,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +@Deprecated /*package*/ interface PublicKeysDaoInterface { @IntRange(from = -1) diff --git a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/PublicKeysSchema.java b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/PublicKeysSchema.java index 6838d976..75c433b7 100644 --- a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/PublicKeysSchema.java +++ b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/authorization/PublicKeysSchema.java @@ -4,6 +4,7 @@ package com.solana.mobilewalletadapter.walletlib.authorization; +@Deprecated /*package*/ interface PublicKeysSchema { String TABLE_PUBLIC_KEYS = "public_keys"; diff --git a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/protocol/MobileWalletAdapterServer.java b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/protocol/MobileWalletAdapterServer.java index 8692d465..84c83850 100644 --- a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/protocol/MobileWalletAdapterServer.java +++ b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/protocol/MobileWalletAdapterServer.java @@ -234,23 +234,21 @@ private void onAuthorizationComplete(@NonNull NotifyOnCompleteFuture" + ", walletUriBase=" + walletUriBase + - ", accounts=" + Arrays.toString(accounts) + + ", account=" + account + '}'; } } diff --git a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/scenario/AuthorizeRequest.java b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/scenario/AuthorizeRequest.java index 0cc62de9..7676d466 100644 --- a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/scenario/AuthorizeRequest.java +++ b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/scenario/AuthorizeRequest.java @@ -117,11 +117,11 @@ public void completeWithAuthorize(@NonNull byte[] publicKey, mRequest.complete(new Result(accounts, walletUriBase, scope, null)); } - public void completeWithAuthorize(@NonNull AuthorizedAccount[] accounts, + public void completeWithAuthorize(@NonNull AuthorizedAccount account, // TODO(#44): support multiple addresses @Nullable Uri walletUriBase, @Nullable byte[] scope, @Nullable SignInResult signInResult) { - mRequest.complete(new Result(accounts, walletUriBase, scope, signInResult)); + mRequest.complete(new Result(new AuthorizedAccount[] { account }, walletUriBase, scope, signInResult)); } public void completeWithDecline() { diff --git a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/scenario/LocalScenario.java b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/scenario/LocalScenario.java index 7e973a5c..6c2b6f51 100644 --- a/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/scenario/LocalScenario.java +++ b/android/walletlib/src/main/java/com/solana/mobilewalletadapter/walletlib/scenario/LocalScenario.java @@ -221,11 +221,9 @@ public void authorize(@NonNull MobileWalletAdapterServer.AuthorizeRequest reques final String name = request.identityName != null ? request.identityName : ""; final Uri uri = request.identityUri != null ? request.identityUri : Uri.EMPTY; final Uri relativeIconUri = request.iconUri != null ? request.iconUri : Uri.EMPTY; - final AuthorizedAccount account = authorize.accounts[0]; // TODO(#44): support multiple addresses - final AuthRecord authRecord = mAuthRepository.issue( - name, uri, relativeIconUri, account.publicKey, - account.accountLabel, chain, authorize.walletUriBase, - authorize.scope); + final AuthRecord authRecord = mAuthRepository.issue(name, uri, + relativeIconUri, authorize.accounts[0], // TODO(#44): support multiple addresses + chain, authorize.walletUriBase, authorize.scope); Log.d(TAG, "Authorize request completed successfully; issued auth: " + authRecord); synchronized (mLock) { mActiveAuthorization = authRecord; @@ -233,7 +231,7 @@ public void authorize(@NonNull MobileWalletAdapterServer.AuthorizeRequest reques final String authToken = mAuthRepository.toAuthToken(authRecord); request.complete(new MobileWalletAdapterServer.AuthorizationResult( - authToken, authorize.accounts, + authToken, authorize.accounts[0], // TODO(#44): support multiple addresses authorize.walletUriBase, authorize.signInResult)); } else { request.completeExceptionally(new MobileWalletAdapterServer.RequestDeclinedException( @@ -307,8 +305,8 @@ private void doReauthorize(@NonNull MobileWalletAdapterServer.AuthorizeRequest r mIoHandler.post(() -> request.complete( new MobileWalletAdapterServer.AuthorizationResult( - authToken, authRecord.publicKey, authRecord.accountLabel, - authRecord.walletUriBase))); + authToken, authRecord.authorizedAccount(), + authRecord.walletUriBase, null))); } catch (ExecutionException e) { final Throwable cause = e.getCause(); assert(cause instanceof Exception); // expected to always be an Exception