Skip to content

Commit

Permalink
feat: migrate Coinbase to use Hub
Browse files Browse the repository at this point in the history
  • Loading branch information
mikasackermn committed Dec 2, 2024
1 parent 7f59449 commit 3151b35
Show file tree
Hide file tree
Showing 12 changed files with 255 additions and 51 deletions.
2 changes: 1 addition & 1 deletion wallets/provider-all/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import * as braavos from '@rango-dev/provider-braavos';
import * as brave from '@rango-dev/provider-brave';
import * as clover from '@rango-dev/provider-clover';
import * as coin98 from '@rango-dev/provider-coin98';
import * as coinbase from '@rango-dev/provider-coinbase';
import { versions as coinbase } from '@rango-dev/provider-coinbase';
import * as cosmostation from '@rango-dev/provider-cosmostation';
import * as defaultInjected from '@rango-dev/provider-default';
import * as enkrypt from '@rango-dev/provider-enkrypt';
Expand Down
12 changes: 6 additions & 6 deletions wallets/provider-coinbase/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@
"version": "0.40.1-next.1",
"license": "MIT",
"type": "module",
"source": "./src/index.ts",
"main": "./dist/index.js",
"source": "./src/mod.ts",
"main": "./dist/mod.js",
"exports": {
".": "./dist/index.js"
".": "./dist/mod.js"
},
"typings": "dist/index.d.ts",
"typings": "dist/mod.d.ts",
"files": [
"dist",
"src"
],
"scripts": {
"build": "node ../../scripts/build/command.mjs --path wallets/provider-coinbase",
"build": "node ../../scripts/build/command.mjs --path wallets/provider-coinbase --inputs src/mod.ts",
"ts-check": "tsc --declaration --emitDeclarationOnly -p ./tsconfig.json",
"clean": "rimraf dist",
"format": "prettier --write '{.,src}/**/*.{ts,tsx}'",
Expand All @@ -30,4 +30,4 @@
"publishConfig": {
"access": "public"
}
}
}
28 changes: 28 additions & 0 deletions wallets/provider-coinbase/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { type ProviderInfo } from '@rango-dev/wallets-core';
import { LegacyNetworks } from '@rango-dev/wallets-core/legacy';

export const EVM_SUPPORTED_CHAINS = [
LegacyNetworks.ETHEREUM,
LegacyNetworks.POLYGON,
];

export const WALLET_ID = 'coinbase';

export const info: ProviderInfo = {
name: 'Coinbase',
icon: 'https://raw.githubusercontent.com/rango-exchange/assets/main/wallets/coinbase/icon.svg',
extensions: {
chrome:
'https://chrome.google.com/webstore/detail/coinbase-wallet-extension/hnfanknocfeofbddgcijnmhnfnkdnaad',
brave:
'https://chrome.google.com/webstore/detail/coinbase-wallet-extension/hnfanknocfeofbddgcijnmhnfnkdnaad',
homepage: 'https://www.coinbase.com/wallet',
},
properties: [
{
name: 'detached',
// if you are adding a new namespace, don't forget to also update `getWalletInfo`
value: ['evm', 'solana'],
},
],
};
41 changes: 0 additions & 41 deletions wallets/provider-coinbase/src/helpers.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ import type {
} from '@rango-dev/wallets-shared';
import type { BlockchainMeta, SignerFactory } from 'rango-types';

import {
type LegacyProviderInterface,
LegacyNetworks as Networks,
} from '@rango-dev/wallets-core/legacy';
import {
canEagerlyConnectToEvm,
canSwitchNetworkToEvm,
chooseInstance,
getEvmAccounts,
Networks,
switchNetworkForEvm,
WalletTypes,
} from '@rango-dev/wallets-shared';
Expand All @@ -25,7 +28,8 @@ import {
solanaBlockchain,
} from 'rango-types';

import { coinbase as coinbase_instance, getSolanaAccounts } from './helpers.js';
import { coinbase as coinbase_instance, getSolanaAccounts } from '../utils.js';

import signer from './signer.js';

const WALLET = WalletTypes.COINBASE;
Expand Down Expand Up @@ -135,3 +139,17 @@ export const getWalletInfo: (allBlockChains: BlockchainMeta[]) => WalletInfo = (
supportedChains: [...evms, ...solana],
};
};

const legacyProvider: LegacyProviderInterface = {
config,
getInstance,
connect,
subscribe,
switchNetwork,
canSwitchNetworkTo,
getSigners,
getWalletInfo,
canEagerConnect,
};

export { legacyProvider };
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { SignerFactory } from 'rango-types';

import { getNetworkInstance, Networks } from '@rango-dev/wallets-shared';
import { LegacyNetworks as Networks } from '@rango-dev/wallets-core/legacy';
import { getNetworkInstance } from '@rango-dev/wallets-shared';
import { DefaultSignerFactory, TransactionType as TxType } from 'rango-types';

import { CustomSolanaSigner } from './solana-signer.js';
Expand Down
11 changes: 11 additions & 0 deletions wallets/provider-coinbase/src/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { defineVersions } from '@rango-dev/wallets-core/utils';

import { legacyProvider } from './legacy/index.js';
import { provider } from './provider.js';

const versions = defineVersions()
.version('0.0.0', legacyProvider)
.version('1.0.0', provider)
.build();

export { versions };
30 changes: 30 additions & 0 deletions wallets/provider-coinbase/src/namespaces/evm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type { EvmActions } from '@rango-dev/wallets-core/namespaces/evm';

import { NamespaceBuilder } from '@rango-dev/wallets-core';
import { builders as commonBuilders } from '@rango-dev/wallets-core/namespaces/common';
import { actions, builders } from '@rango-dev/wallets-core/namespaces/evm';

import { WALLET_ID } from '../constants.js';
import { evmCoinbase } from '../utils.js';

const [changeAccountSubscriber, changeAccountCleanup] =
actions.changeAccountSubscriber(evmCoinbase);

const connect = builders
.connect()
.action(actions.connect(evmCoinbase))
.before(changeAccountSubscriber)
.or(changeAccountCleanup)
.build();

const disconnect = commonBuilders
.disconnect<EvmActions>()
.after(changeAccountCleanup)
.build();

const evm = new NamespaceBuilder<EvmActions>('EVM', WALLET_ID)
.action(connect)
.action(disconnect)
.build();

export { evm };
62 changes: 62 additions & 0 deletions wallets/provider-coinbase/src/namespaces/solana.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import type { CaipAccount } from '@rango-dev/wallets-core/namespaces/common';
import type { SolanaActions } from '@rango-dev/wallets-core/namespaces/solana';

import { NamespaceBuilder } from '@rango-dev/wallets-core';
import { builders as commonBuilders } from '@rango-dev/wallets-core/namespaces/common';
import {
actions,
builders,
CAIP_NAMESPACE,
CAIP_SOLANA_CHAIN_ID,
} from '@rango-dev/wallets-core/namespaces/solana';
import { CAIP } from '@rango-dev/wallets-core/utils';
import { getSolanaAccounts } from '@rango-dev/wallets-shared';

import { WALLET_ID } from '../constants.js';
import { solanaCoinbase } from '../utils.js';

const [changeAccountSubscriber, changeAccountCleanup] =
actions.changeAccountSubscriber(solanaCoinbase);

const connect = builders
.connect()
.action(async function () {
const solanaInstance = solanaCoinbase();
const result = await getSolanaAccounts({
instance: solanaInstance,
meta: [],
});
if (Array.isArray(result)) {
throw new Error(
'Expecting solana response to be a single value, not an array.'
);
}

const formatAccounts = result.accounts.map(
(account) =>
CAIP.AccountId.format({
address: account,
chainId: {
namespace: CAIP_NAMESPACE,
reference: CAIP_SOLANA_CHAIN_ID,
},
}) as CaipAccount
);

return formatAccounts;
})
.before(changeAccountSubscriber)
.or(changeAccountCleanup)
.build();

const disconnect = commonBuilders
.disconnect<SolanaActions>()
.after(changeAccountCleanup)
.build();

const solana = new NamespaceBuilder<SolanaActions>('Solana', WALLET_ID)
.action(connect)
.action(disconnect)
.build();

export { solana };
22 changes: 22 additions & 0 deletions wallets/provider-coinbase/src/provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ProviderBuilder } from '@rango-dev/wallets-core';

import { info, WALLET_ID } from './constants.js';
import { evm } from './namespaces/evm.js';
import { solana } from './namespaces/solana.js';
import { coinbase as coinbaseInstance } from './utils.js';

const provider = new ProviderBuilder(WALLET_ID)
.init(function (context) {
const [, setState] = context.state();

if (coinbaseInstance()) {
setState('installed', true);
console.debug('[coinbase] instance detected.', context);
}
})
.config('info', info)
.add('solana', solana)
.add('evm', evm)
.build();

export { provider };
73 changes: 73 additions & 0 deletions wallets/provider-coinbase/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import type { ProviderAPI as EvmProviderApi } from '@rango-dev/wallets-core/namespaces/evm';
import type { ProviderAPI as SolanaProviderApi } from '@rango-dev/wallets-core/namespaces/solana';
import type { ProviderConnectResult } from '@rango-dev/wallets-shared';

import { LegacyNetworks } from '@rango-dev/wallets-core/legacy';

type Provider = Map<string, unknown>;

export function coinbase(): Provider | null {
const { coinbaseWalletExtension, coinbaseSolana } = window;

if (!coinbaseSolana && !coinbaseWalletExtension) {
return null;
}

const instances = new Map();

if (coinbaseWalletExtension) {
instances.set(LegacyNetworks.ETHEREUM, coinbaseWalletExtension);
}

if (coinbaseSolana) {
instances.set(LegacyNetworks.SOLANA, coinbaseSolana);
}

return instances;
}

export function evmCoinbase(): EvmProviderApi {
const instances = coinbase();

const evmInstance = instances?.get(LegacyNetworks.ETHEREUM);

if (!evmInstance) {
throw new Error(
'Coinbase not injected or EVM not enabled. Please check your wallet.'
);
}

return evmInstance as EvmProviderApi;
}

export function solanaCoinbase(): SolanaProviderApi {
const instance = coinbase();
const solanaInstance = instance?.get(LegacyNetworks.SOLANA);

if (!solanaInstance) {
throw new Error(
'Coinbase not injected or Solana not enabled. Please check your wallet.'
);
}

return solanaInstance;
}

export async function getSolanaAccounts(
instance: any
): Promise<ProviderConnectResult[]> {
const solanaInstance = await instance.get(LegacyNetworks.SOLANA);
const results: ProviderConnectResult[] = [];

if (solanaInstance) {
await solanaInstance.connect();
const account = solanaInstance.publicKey.toString();

results.push({
accounts: account ? [account] : [],
chainId: LegacyNetworks.SOLANA,
});
}

return results;
}

0 comments on commit 3151b35

Please sign in to comment.