Skip to content
Closed
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
2 changes: 2 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ VITE_MONAD_NODE_URL=https://rpc.monad.xyz
VITE_PLASMA_NODE_URL=https://rpc.plasma.to
VITE_MEGAETH_NODE_URL=https://mainnet.megaeth.com/rpc
VITE_KATANA_NODE_URL=https://rpc.katana.network
VITE_SEI_NODE_URL=https://evm-rpc.sei-apis.com/
VITE_THORCHAIN_NODE_URL=https://api.thorchain.shapeshift.com/lcd
VITE_MAYACHAIN_NODE_URL=https://api.mayachain.shapeshift.com/lcd
VITE_SOLANA_NODE_URL=https://api.solana.shapeshift.com/api/v1/jsonrpc
Expand Down Expand Up @@ -304,6 +305,7 @@ VITE_FEATURE_HYPEREVM=true
VITE_FEATURE_MEGAETH=false
VITE_FEATURE_NEAR=true
VITE_FEATURE_KATANA=true
VITE_FEATURE_SEI=false

# Yield.xyz Feature Flag
VITE_FEATURE_YIELD_XYZ=true
Expand Down
1 change: 1 addition & 0 deletions .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ VITE_FEATURE_WC_DIRECT_CONNECTION=true
VITE_FEATURE_CETUS_SWAP=true
VITE_FEATURE_MEGAETH=true
VITE_FEATURE_KATANA=true
VITE_FEATURE_SEI=true
VITE_FEATURE_TON=true
VITE_FEATURE_STONFI_SWAP=true
VITE_FEATURE_ACROSS_SWAP=true
Expand Down
10 changes: 10 additions & 0 deletions headers/csps/chains/sei.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { loadEnv } from 'vite'

import type { Csp } from '../../types'

const mode = process.env.MODE ?? process.env.NODE_ENV ?? 'development'
const env = loadEnv(mode, process.cwd(), '')

export const csp: Csp = {
'connect-src': [env.VITE_SEI_NODE_URL],
}
2 changes: 2 additions & 0 deletions headers/csps/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { csp as near } from './chains/near'
import { csp as optimism } from './chains/optimism'
import { csp as plasma } from './chains/plasma'
import { csp as polygon } from './chains/polygon'
import { csp as sei } from './chains/sei'
import { csp as solana } from './chains/solana'
import { csp as starknet } from './chains/starknet'
import { csp as sui } from './chains/sui'
Expand Down Expand Up @@ -131,6 +132,7 @@ export const csps = [
monad,
near,
plasma,
sei,
trustwallet,
coincap,
coingecko,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"eip155:1329/slip44:60":"sei-network"}
2 changes: 2 additions & 0 deletions packages/caip/src/adapters/coingecko/generated/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import monad from "./eip155_143/adapter.json";
import hyperevm from "./eip155_999/adapter.json";
import plasma from "./eip155_9745/adapter.json";
import katana from "./eip155_747474/adapter.json";
import sei from "./eip155_1329/adapter.json";
import megaeth from "./eip155_4326/adapter.json";
import cosmos from "./cosmos_cosmoshub-4/adapter.json";
import thorchain from "./cosmos_thorchain-1/adapter.json";
Expand Down Expand Up @@ -43,6 +44,7 @@ export {
hyperevm,
plasma,
katana,
sei,
megaeth,
cosmos,
thorchain,
Expand Down
6 changes: 6 additions & 0 deletions packages/caip/src/adapters/coingecko/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
optimismChainId,
plasmaChainId,
polygonChainId,
seiChainId,
solanaChainId,
starknetChainId,
suiChainId,
Expand Down Expand Up @@ -51,6 +52,7 @@ export enum CoingeckoAssetPlatform {
HyperEvm = 'hyperevm',
Plasma = 'plasma',
Katana = 'katana',
Sei = 'sei-v2',
MegaEth = 'megaeth',
Solana = 'solana',
Starknet = 'starknet',
Expand Down Expand Up @@ -112,6 +114,8 @@ export const chainIdToCoingeckoAssetPlatform = (chainId: ChainId): string => {
return CoingeckoAssetPlatform.Plasma
case CHAIN_REFERENCE.KatanaMainnet:
return CoingeckoAssetPlatform.Katana
case CHAIN_REFERENCE.SeiMainnet:
return CoingeckoAssetPlatform.Sei
case CHAIN_REFERENCE.MegaEthMainnet:
return CoingeckoAssetPlatform.MegaEth
default:
Expand Down Expand Up @@ -221,6 +225,8 @@ export const coingeckoAssetPlatformToChainId = (
return plasmaChainId
case CoingeckoAssetPlatform.Katana:
return katanaChainId
case CoingeckoAssetPlatform.Sei:
return seiChainId
case CoingeckoAssetPlatform.MegaEth:
return megaethChainId
case CoingeckoAssetPlatform.Cosmos:
Expand Down
3 changes: 3 additions & 0 deletions packages/caip/src/adapters/coingecko/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ describe('adapters:coingecko:utils', () => {
'eip155:747474': {
'eip155:747474/slip44:60': 'katana',
},
'eip155:1329': {
'eip155:1329/slip44:60': 'sei-network',
},
'near:mainnet': {
'near:mainnet/slip44:397': 'near',
},
Expand Down
17 changes: 17 additions & 0 deletions packages/caip/src/adapters/coingecko/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ import {
plasmaChainId,
polygonAssetId,
polygonChainId,
seiAssetId,
seiChainId,
solanaChainId,
solAssetId,
starknetAssetId,
Expand Down Expand Up @@ -303,6 +305,20 @@ export const parseData = (coins: CoingeckoCoin[]): AssetMap => {
}
}

if (Object.keys(platforms).includes(CoingeckoAssetPlatform.Sei)) {
try {
const assetId = toAssetId({
chainNamespace: CHAIN_NAMESPACE.Evm,
chainReference: CHAIN_REFERENCE.SeiMainnet,
assetNamespace: 'erc20',
assetReference: platforms[CoingeckoAssetPlatform.Sei],
})
prev[seiChainId][assetId] = id
} catch {
// unable to create assetId, skip token
}
}

if (Object.keys(platforms).includes(CoingeckoAssetPlatform.Starknet)) {
try {
const assetId = toAssetId({
Expand Down Expand Up @@ -361,6 +377,7 @@ export const parseData = (coins: CoingeckoCoin[]): AssetMap => {
[plasmaChainId]: { [plasmaAssetId]: 'plasma' },
[megaethChainId]: { [megaethAssetId]: 'ethereum' },
[katanaChainId]: { [katanaAssetId]: 'katana' },
[seiChainId]: { [seiAssetId]: 'sei-network' },
[solanaChainId]: { [solAssetId]: 'solana' },
[starknetChainId]: { [starknetAssetId]: 'starknet' },
[tronChainId]: { [tronAssetId]: 'tron' },
Expand Down
5 changes: 5 additions & 0 deletions packages/caip/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const hyperEvmAssetId: AssetId = 'eip155:999/slip44:60'
export const plasmaAssetId: AssetId = 'eip155:9745/slip44:60'
export const megaethAssetId: AssetId = 'eip155:4326/slip44:60'
export const katanaAssetId: AssetId = 'eip155:747474/slip44:60'
export const seiAssetId: AssetId = 'eip155:1329/slip44:60'
export const solAssetId: AssetId = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501'
export const wrappedSolAssetId: AssetId =
'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:So11111111111111111111111111111111111111112'
Expand Down Expand Up @@ -81,6 +82,7 @@ export const hyperEvmChainId: ChainId = 'eip155:999'
export const plasmaChainId: ChainId = 'eip155:9745'
export const megaethChainId: ChainId = 'eip155:4326'
export const katanaChainId: ChainId = 'eip155:747474'
export const seiChainId: ChainId = 'eip155:1329'

export const cosmosChainId: ChainId = 'cosmos:cosmoshub-4'
export const thorchainChainId: ChainId = 'cosmos:thorchain-1'
Expand Down Expand Up @@ -133,6 +135,7 @@ export const CHAIN_REFERENCE = {
PlasmaMainnet: '9745', // https://chainlist.org/chain/9745
MegaEthMainnet: '4326',
KatanaMainnet: '747474', // https://docs.katana.network
SeiMainnet: '1329', // https://docs.sei.io
SolanaMainnet: '5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', // https://namespaces.chainagnostic.org/solana/caip2
TronMainnet: '0x2b6653dc', // https://developers.tron.network/docs/networks
SuiMainnet: '35834a8a', // First 8 chars of SUI mainnet genesis hash
Expand Down Expand Up @@ -178,6 +181,7 @@ export const ASSET_REFERENCE = {
Plasma: '60', // evm chain which uses ethereum derivation path as common practice
MegaEth: '60', // evm chain which uses ethereum derivation path as common practice
Katana: '60', // evm chain which uses ethereum derivation path as common practice
Sei: '60', // evm chain which uses ethereum derivation path as common practice
Solana: '501',
Tron: '195',
Sui: '784',
Expand Down Expand Up @@ -208,6 +212,7 @@ export const VALID_CHAIN_IDS: ValidChainMap = Object.freeze({
CHAIN_REFERENCE.PlasmaMainnet,
CHAIN_REFERENCE.MegaEthMainnet,
CHAIN_REFERENCE.KatanaMainnet,
CHAIN_REFERENCE.SeiMainnet,
],
[CHAIN_NAMESPACE.CosmosSdk]: [
CHAIN_REFERENCE.CosmosHubMainnet,
Expand Down
9 changes: 9 additions & 0 deletions packages/chain-adapters/src/evm/EvmBaseAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
supportsOptimism,
supportsPlasma,
supportsPolygon,
supportsSei,
} from '@shapeshiftoss/hdwallet-core'
import type { Bip44Params, EvmChainId, RootBip44Params } from '@shapeshiftoss/types'
import { KnownChainIds } from '@shapeshiftoss/types'
Expand Down Expand Up @@ -88,6 +89,7 @@ export const evmChainIds = [
KnownChainIds.PlasmaMainnet,
KnownChainIds.MegaEthMainnet,
KnownChainIds.KatanaMainnet,
KnownChainIds.SeiMainnet,
] as const

export type EvmChainAdapter = EvmBaseAdapter<EvmChainId>
Expand Down Expand Up @@ -192,6 +194,8 @@ export abstract class EvmBaseAdapter<T extends EvmChainId> implements IChainAdap
return supportsMegaEth(wallet)
case Number(fromChainId(KnownChainIds.KatanaMainnet).chainReference):
return supportsKatana(wallet)
case Number(fromChainId(KnownChainIds.SeiMainnet).chainReference):
return supportsSei(wallet)
default:
return false
}
Expand Down Expand Up @@ -289,6 +293,11 @@ export abstract class EvmBaseAdapter<T extends EvmChainId> implements IChainAdap
symbol: 'ETH',
explorer: 'https://katanascan.com',
},
[KnownChainIds.SeiMainnet]: {
name: 'SEI',
symbol: 'SEI',
explorer: 'https://seitrace.com',
},
}[this.chainId]

try {
Expand Down
1 change: 1 addition & 0 deletions packages/chain-adapters/src/evm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ export * as hyperevm from './hyperevm'
export * as plasma from './plasma'
export * as megaeth from './megaeth'
export * as katana from './katana'
export * as sei from './sei'
57 changes: 57 additions & 0 deletions packages/chain-adapters/src/evm/sei/SeiChainAdapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import type { AssetId } from '@shapeshiftoss/caip'
import { ASSET_REFERENCE, seiAssetId } from '@shapeshiftoss/caip'
import type { RootBip44Params } from '@shapeshiftoss/types'
import { KnownChainIds } from '@shapeshiftoss/types'

import { ChainAdapterDisplayName } from '../../types'
import type { TokenInfo } from '../SecondClassEvmAdapter'
import { SecondClassEvmAdapter } from '../SecondClassEvmAdapter'

const SUPPORTED_CHAIN_IDS = [KnownChainIds.SeiMainnet]
const DEFAULT_CHAIN_ID = KnownChainIds.SeiMainnet

export type ChainAdapterArgs = {
rpcUrl: string
getKnownTokens: () => TokenInfo[]
}

export const isSeiChainAdapter = (adapter: unknown): adapter is ChainAdapter => {
return (adapter as ChainAdapter).getType() === KnownChainIds.SeiMainnet
}
Comment on lines +18 to +20
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

isSeiChainAdapter will throw on null/undefined input — the adapter: unknown type does not preclude null, and (adapter as ChainAdapter).getType() will produce a TypeError without a null guard.

🛡️ Proposed fix
 export const isSeiChainAdapter = (adapter: unknown): adapter is ChainAdapter => {
+  if (!adapter) return false
   return (adapter as ChainAdapter).getType() === KnownChainIds.SeiMainnet
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/chain-adapters/src/evm/sei/SeiChainAdapter.ts` around lines 18 - 20,
The type-guard isSeiChainAdapter currently calls (adapter as
ChainAdapter).getType() without null/undefined protection and will throw for
nullish inputs; update isSeiChainAdapter to first check adapter is not
null/undefined and that (adapter as any).getType is a function before calling
it, then return whether getType() === KnownChainIds.SeiMainnet (referencing
isSeiChainAdapter, getType, and KnownChainIds.SeiMainnet in your change).


export class ChainAdapter extends SecondClassEvmAdapter<KnownChainIds.SeiMainnet> {
public static readonly rootBip44Params: RootBip44Params = {
purpose: 44,
coinType: Number(ASSET_REFERENCE.Sei),
accountNumber: 0,
}

constructor(args: ChainAdapterArgs) {
super({
assetId: seiAssetId,
chainId: DEFAULT_CHAIN_ID,
rootBip44Params: ChainAdapter.rootBip44Params,
supportedChainIds: SUPPORTED_CHAIN_IDS,
rpcUrl: args.rpcUrl,
getKnownTokens: args.getKnownTokens,
})
}

getDisplayName() {
return ChainAdapterDisplayName.Sei
}

getName() {
return 'Sei'
}

getType(): KnownChainIds.SeiMainnet {
return KnownChainIds.SeiMainnet
}

getFeeAssetId(): AssetId {
return this.assetId
}
}

export type { TokenInfo }
1 change: 1 addition & 0 deletions packages/chain-adapters/src/evm/sei/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './SeiChainAdapter'
6 changes: 6 additions & 0 deletions packages/chain-adapters/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ type ChainSpecificAccount<T> = ChainSpecific<
[KnownChainIds.PlasmaMainnet]: evm.Account
[KnownChainIds.MegaEthMainnet]: evm.Account
[KnownChainIds.KatanaMainnet]: evm.Account
[KnownChainIds.SeiMainnet]: evm.Account
[KnownChainIds.BitcoinMainnet]: utxo.Account
[KnownChainIds.BitcoinCashMainnet]: utxo.Account
[KnownChainIds.DogecoinMainnet]: utxo.Account
Expand Down Expand Up @@ -101,6 +102,7 @@ type ChainSpecificFeeData<T> = ChainSpecific<
[KnownChainIds.PlasmaMainnet]: evm.FeeData
[KnownChainIds.MegaEthMainnet]: evm.FeeData
[KnownChainIds.KatanaMainnet]: evm.FeeData
[KnownChainIds.SeiMainnet]: evm.FeeData
[KnownChainIds.BitcoinMainnet]: utxo.FeeData
[KnownChainIds.BitcoinCashMainnet]: utxo.FeeData
[KnownChainIds.DogecoinMainnet]: utxo.FeeData
Expand Down Expand Up @@ -186,6 +188,7 @@ export type ChainSignTx = {
[KnownChainIds.PlasmaMainnet]: ETHSignTx
[KnownChainIds.MegaEthMainnet]: ETHSignTx
[KnownChainIds.KatanaMainnet]: ETHSignTx
[KnownChainIds.SeiMainnet]: ETHSignTx
[KnownChainIds.BitcoinMainnet]: BTCSignTx
[KnownChainIds.BitcoinCashMainnet]: BTCSignTx
[KnownChainIds.DogecoinMainnet]: BTCSignTx
Expand Down Expand Up @@ -243,6 +246,7 @@ export type ChainSpecificBuildTxData<T> = ChainSpecific<
[KnownChainIds.PlasmaMainnet]: evm.BuildTxInput
[KnownChainIds.MegaEthMainnet]: evm.BuildTxInput
[KnownChainIds.KatanaMainnet]: evm.BuildTxInput
[KnownChainIds.SeiMainnet]: evm.BuildTxInput
[KnownChainIds.BitcoinMainnet]: utxo.BuildTxInput
[KnownChainIds.BitcoinCashMainnet]: utxo.BuildTxInput
[KnownChainIds.DogecoinMainnet]: utxo.BuildTxInput
Expand Down Expand Up @@ -350,6 +354,7 @@ type ChainSpecificGetFeeDataInput<T> = ChainSpecific<
[KnownChainIds.PlasmaMainnet]: evm.GetFeeDataInput
[KnownChainIds.MegaEthMainnet]: evm.GetFeeDataInput
[KnownChainIds.KatanaMainnet]: evm.GetFeeDataInput
[KnownChainIds.SeiMainnet]: evm.GetFeeDataInput
[KnownChainIds.BitcoinMainnet]: utxo.GetFeeDataInput
[KnownChainIds.BitcoinCashMainnet]: utxo.GetFeeDataInput
[KnownChainIds.DogecoinMainnet]: utxo.GetFeeDataInput
Expand Down Expand Up @@ -422,6 +427,7 @@ export enum ChainAdapterDisplayName {
Plasma = 'Plasma',
MegaEth = 'MegaETH',
Katana = 'Katana',
Sei = 'Sei',
Cosmos = 'Cosmos',
Bitcoin = 'Bitcoin',
BitcoinCash = 'Bitcoin Cash',
Expand Down
2 changes: 2 additions & 0 deletions packages/contracts/src/ethersProviderSingleton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ export const rpcUrlByChainId = (chainId: EvmChainId): string => {
return process.env.VITE_MEGAETH_NODE_URL
case KnownChainIds.KatanaMainnet:
return process.env.VITE_KATANA_NODE_URL
case KnownChainIds.SeiMainnet:
return process.env.VITE_SEI_NODE_URL
default:
return assertUnreachable(chainId)
}
Expand Down
9 changes: 9 additions & 0 deletions packages/contracts/src/viemClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
optimism,
plasma,
polygon,
sei,
} from 'viem/chains'

const megaeth = defineChain({
Expand Down Expand Up @@ -117,6 +118,11 @@ export const viemKatanaClient = createPublicClient({
transport: fallback([process.env.VITE_KATANA_NODE_URL].filter(Boolean).map(url => http(url))),
}) as PublicClient

export const viemSeiClient = createPublicClient({
chain: sei,
transport: fallback([process.env.VITE_SEI_NODE_URL].filter(Boolean).map(url => http(url))),
}) as PublicClient

export const viemClientByChainId: Record<ChainId, PublicClient> = {
[KnownChainIds.EthereumMainnet]: viemEthMainnetClient,
[KnownChainIds.BnbSmartChainMainnet]: viemBscClient,
Expand All @@ -131,6 +137,7 @@ export const viemClientByChainId: Record<ChainId, PublicClient> = {
[KnownChainIds.PlasmaMainnet]: viemPlasmaClient,
[KnownChainIds.MegaEthMainnet]: viemMegaEthClient,
[KnownChainIds.KatanaMainnet]: viemKatanaClient,
[KnownChainIds.SeiMainnet]: viemSeiClient,
}

export const viemNetworkIdByChainId: Record<ChainId, number> = {
Expand All @@ -147,6 +154,7 @@ export const viemNetworkIdByChainId: Record<ChainId, number> = {
[KnownChainIds.PlasmaMainnet]: plasma.id,
[KnownChainIds.MegaEthMainnet]: megaeth.id,
[KnownChainIds.KatanaMainnet]: katana.id,
[KnownChainIds.SeiMainnet]: sei.id,
}

export const viemClientByNetworkId: Record<number, PublicClient> = {
Expand All @@ -163,6 +171,7 @@ export const viemClientByNetworkId: Record<number, PublicClient> = {
[plasma.id]: viemPlasmaClient,
[megaeth.id]: viemMegaEthClient,
[katana.id]: viemKatanaClient,
[sei.id]: viemSeiClient,
}

export const assertGetViemClient = (chainId: ChainId): PublicClient => {
Expand Down
Loading