Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: migrate coin98 to use Hub #992

Open
wants to merge 3 commits into
base: next
Choose a base branch
from
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
4 changes: 2 additions & 2 deletions wallets/provider-all/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as bitget from '@rango-dev/provider-bitget';
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 { versions as coin98 } from '@rango-dev/provider-coin98';
import * as coinbase from '@rango-dev/provider-coinbase';
import * as cosmostation from '@rango-dev/provider-cosmostation';
import * as defaultInjected from '@rango-dev/provider-default';
Expand Down Expand Up @@ -124,7 +124,7 @@ export const allProviders = (
lazyProvider(legacyProviderImportsToVersionsInterface(clover)),
lazyProvider(legacyProviderImportsToVersionsInterface(safepal)),
lazyProvider(legacyProviderImportsToVersionsInterface(brave)),
lazyProvider(legacyProviderImportsToVersionsInterface(coin98)),
coin98,
lazyProvider(legacyProviderImportsToVersionsInterface(coinbase)),
lazyProvider(legacyProviderImportsToVersionsInterface(cosmostation)),
lazyProvider(legacyProviderImportsToVersionsInterface(exodus)),
Expand Down
12 changes: 6 additions & 6 deletions wallets/provider-coin98/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@
"version": "0.41.1-next.6",
"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-coin98",
"build": "node ../../scripts/build/command.mjs --path wallets/provider-coin98 --inputs src/mod.ts",
"ts-check": "tsc --declaration --emitDeclarationOnly -p ./tsconfig.json",
"clean": "rimraf dist",
"format": "prettier --write '{.,src}/**/*.{ts,tsx}'",
Expand All @@ -31,4 +31,4 @@
"publishConfig": {
"access": "public"
}
}
}
22 changes: 22 additions & 0 deletions wallets/provider-coin98/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { type ProviderInfo } from '@rango-dev/wallets-core';

export const WALLET_ID = 'coin98';

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

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { LegacyProviderInterface } from '@rango-dev/wallets-core/legacy';
import type {
CanSwitchNetwork,
Connect,
Expand All @@ -18,7 +19,8 @@ import {
} from '@rango-dev/wallets-shared';
import { evmBlockchains, solanaBlockchain } from 'rango-types';

import { coin98 as coin98_instances, getSolanaAccounts } from './helpers.js';
import { coin98 as coin98_instances, getSolanaAccounts } from '../utils.js';

import signer from './signer.js';

const WALLET = WalletTypes.COIN98;
Expand Down Expand Up @@ -117,5 +119,33 @@ export const getWalletInfo: (allBlockChains: BlockchainMeta[]) => WalletInfo = (
},
color: '#1d1c25',
supportedChains: [...evms, ...solana],
needsNamespace: {
selection: 'multiple',
data: [
{
label: 'EVM',
value: 'EVM',
id: 'ETH',
},
{
label: 'Solana',
value: 'Solana',
id: 'SOLANA',
},
],
},
};
};

const buildLegacyProvider: () => LegacyProviderInterface = () => ({
config,
getInstance,
connect,
subscribe,
switchNetwork,
canSwitchNetworkTo,
getSigners,
getWalletInfo,
});

export { buildLegacyProvider };
12 changes: 12 additions & 0 deletions wallets/provider-coin98/src/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { defineVersions } from '@rango-dev/wallets-core/utils';

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

const versions = () =>
defineVersions()
.version('0.0.0', buildLegacyProvider())
.version('1.0.0', buildProvider())
.build();

export { versions };
36 changes: 36 additions & 0 deletions wallets/provider-coin98/src/namespaces/evm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
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 { evmCoin98 } from '../utils.js';

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

/*
* TODO: If user imported a private key for EVM, it hasn't solana.
* when trying to connect to solana for this user we go through `-32603` which is an internal error.
* If phantom added an specific error code for this situation, we can consider handling the error here.
* @see https://docs.phantom.app/solana/errors
*/
const connect = builders
.connect()
.action(actions.connect(evmCoin98))
.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 };
64 changes: 64 additions & 0 deletions wallets/provider-coin98/src/namespaces/solana.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
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 { WALLET_ID } from '../constants.js';
import { getSolanaAccounts, solanaCoin98 } from '../utils.js';

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

/*
* TODO: If user imported a private key for EVM, it hasn't solana.
* when trying to connect to solana for this user we go through `-32603` which is an internal error.
* If phantom added an specific error code for this situation, we can consider handling the error here.
* @see https://docs.phantom.app/solana/errors
*/
const connect = builders
.connect()
.action(async function () {
const solanaInstance = solanaCoin98();
const result = await getSolanaAccounts(solanaInstance);
if (Array.isArray(result)) {
throw new Error(
'Expecting solana response to be a single value, not an array.'
);
}

const formatAccounts = result.accounts.map(
(account) =>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you didn't specify the return type for getSolanaAccounts in utitls. this has an implicit any type. Please fix it in there or at least declare account as any explicitly.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

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 };
23 changes: 23 additions & 0 deletions wallets/provider-coin98/src/provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
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 { coin98 as coin98Instances } from './utils.js';

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

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

export { buildProvider };
73 changes: 73 additions & 0 deletions wallets/provider-coin98/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 { LegacyNetworks } from '@rango-dev/wallets-core/legacy';
import {
Networks,
type ProviderConnectResult,
} from '@rango-dev/wallets-shared';

export function coin98() {
const { coin98, ethereum } = window;

if (!coin98) {
return null;
}

const instances = new Map();

// When disabled overring metamask
if (coin98.provider) {
instances.set(Networks.ETHEREUM, coin98.provider);
}
if (ethereum && ethereum.isCoin98) {
instances.set(Networks.ETHEREUM, ethereum);
}
if (coin98.sol) {
instances.set(Networks.SOLANA, coin98.sol);
}

return instances;
}

/*
*This is how coin98 is getting solana accounts.
*That's the reason we haven't moved it to `shared`
*/
export async function getSolanaAccounts(
instance: any
): Promise<ProviderConnectResult> {
await instance.enable();
const accounts = await instance.request({ method: 'sol_accounts' });
return {
accounts,
chainId: LegacyNetworks.SOLANA,
};
}

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

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

return solanaInstance;
}

export function evmCoin98(): EvmProviderApi {
const instances = coin98();

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

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

return evmInstance as EvmProviderApi;
}