feat: fetch EVM token info from backend API

This commit is contained in:
c4605
2025-05-14 22:46:22 +08:00
parent 6ef7ea2696
commit a3782b5dd9
9 changed files with 227 additions and 484 deletions

View File

@@ -1,6 +1,8 @@
import { BroSDK } from "../src" import { BroSDK } from "../src"
import { getAllAddresses } from "../src/evmUtils/contractHelpers" import { getEVMOnChainConfig } from "../src/evmUtils/apiHelpers/getEVMOnChainConfig"
import { getEVMSupportedRoutes } from "../src/evmUtils/apiHelpers/getEVMSupportedRoutes"
import { getSDKContext } from "../src/lowlevelUnstableInfos" import { getSDKContext } from "../src/lowlevelUnstableInfos"
import { props } from "../src/utils/promiseHelpers"
import { _allKnownEVMChains } from "../src/utils/types/knownIds" import { _allKnownEVMChains } from "../src/utils/types/knownIds"
async function print(matchers: { chain: string[] }): Promise<void> { async function print(matchers: { chain: string[] }): Promise<void> {
@@ -13,8 +15,11 @@ async function print(matchers: { chain: string[] }): Promise<void> {
await Promise.all( await Promise.all(
chainIds.map(chainId => chainIds.map(chainId =>
getAllAddresses(ctx, chainId).then(resp => { props({
console.log(chainId, resp?.onChainAddresses ?? "undefined") config: getEVMOnChainConfig(ctx, chainId),
routes: getEVMSupportedRoutes(ctx, chainId),
}).then(resp => {
console.log(chainId, resp)
return resp return resp
}), }),
), ),

View File

@@ -0,0 +1,81 @@
import { EVMAddress } from "../../sdkUtils/types"
import { SDKGlobalContext } from "../../sdkUtils/types.internal"
import { requestAPI } from "../../utils/apiHelpers"
import {
_allKnownEVMMainnetChains,
_allKnownEVMTestnetChains,
KnownChainId,
} from "../../utils/types/knownIds"
import { EVMEndpointContract } from "../evmContractAddresses"
export type EVMOnChainConfigForEVMChain = null | Partial<
Record<EVMEndpointContract, EVMAddress>
>
export type EVMOnChainConfigByEVMChain = Partial<
Record<KnownChainId.EVMChain, EVMOnChainConfigForEVMChain>
>
export async function getEVMOnChainConfig(
sdkContext: SDKGlobalContext,
chainId: KnownChainId.EVMChain,
): Promise<EVMOnChainConfigForEVMChain> {
const config = await getEVMOnChainConfigByChainType(
sdkContext,
KnownChainId.isEVMMainnetChain(chainId) ? "mainnet" : "testnet",
)
return config[chainId] ?? null
}
export async function getEVMOnChainConfigByChainType(
sdkContext: SDKGlobalContext,
network: "mainnet" | "testnet",
): Promise<EVMOnChainConfigByEVMChain> {
if (
sdkContext.evm.onChainConfigCache != null &&
sdkContext.evm.onChainConfigCache.get(network) != null
) {
return sdkContext.evm.onChainConfigCache.get(network)!
}
const promise = _getEVMOnChainConfigByChainTypeImpl(
sdkContext,
network,
).catch(err => {
const cachedPromise = sdkContext.evm.onChainConfigCache?.get(network)
if (promise === cachedPromise) {
sdkContext.evm.onChainConfigCache?.delete(network)
}
throw err
})
sdkContext.evm.onChainConfigCache?.set(network, promise)
return promise
}
async function _getEVMOnChainConfigByChainTypeImpl(
sdkContext: SDKGlobalContext,
network: "mainnet" | "testnet",
): Promise<EVMOnChainConfigByEVMChain> {
const evmChains =
network === "mainnet"
? _allKnownEVMMainnetChains
: _allKnownEVMTestnetChains
const resp = await requestAPI<null | {
config: Server_Resp_EVMOnChainConfigByEVMChain
}>(sdkContext, {
method: "POST",
path: "/2024-10-01/evm/on-chain-config",
body: { chains: evmChains },
})
if (resp == null) return {}
return resp.config
}
type Server_Resp_EVMOnChainConfigByEVMChain = Partial<
Record<
/* XLink SDK EVMChain */ string,
null | Partial<Record</* contract name enum */ string, `0x${string}`>>
>
>

View File

@@ -1,14 +1,20 @@
import {
EVMAddress,
StacksContractAddress,
TokenId,
} from "../../sdkUtils/types"
import { SDKGlobalContext } from "../../sdkUtils/types.internal"
import { getStacksToken } from "../../stacksUtils/contractHelpers" import { getStacksToken } from "../../stacksUtils/contractHelpers"
import { requestAPI } from "../../utils/apiHelpers" import { requestAPI } from "../../utils/apiHelpers"
import { BigNumber } from "../../utils/BigNumber" import { BigNumber } from "../../utils/BigNumber"
import { isNotNull } from "../../utils/typeHelpers" import { isNotNull } from "../../utils/typeHelpers"
import { KnownChainId, KnownTokenId } from "../../utils/types/knownIds" import { createEVMToken, KnownChainId, KnownTokenId } from "../../utils/types/knownIds"
import { StacksContractAddress } from "../../sdkUtils/types" import { evmChainIdToKnownChainId } from "../evmClients"
import { SDKGlobalContext } from "../../sdkUtils/types.internal"
export interface EVMSupportedRoute { export interface EVMSupportedRoute {
evmChain: KnownChainId.EVMChain evmChain: KnownChainId.EVMChain
evmToken: KnownTokenId.EVMToken evmToken: KnownTokenId.EVMToken
evmTokenAddress: EVMAddress
stacksChain: KnownChainId.StacksChain stacksChain: KnownChainId.StacksChain
stacksToken: KnownTokenId.StacksToken stacksToken: KnownTokenId.StacksToken
proxyStacksTokenContractAddress: null | StacksContractAddress proxyStacksTokenContractAddress: null | StacksContractAddress
@@ -71,8 +77,7 @@ async function _getEVMSupportedRoutes(
const routes = await Promise.all( const routes = await Promise.all(
resp.routes.map(async (route): Promise<null | EVMSupportedRoute> => { resp.routes.map(async (route): Promise<null | EVMSupportedRoute> => {
const evmChain = route.evmChain as KnownChainId.KnownChain const evmChain = evmChainIdToKnownChainId(BigInt(route.evmChainId))
const evmToken = route.evmToken as KnownTokenId.KnownToken
const stacksToken = await getStacksToken( const stacksToken = await getStacksToken(
sdkContext, sdkContext,
stacksChain, stacksChain,
@@ -80,12 +85,15 @@ async function _getEVMSupportedRoutes(
) )
if (stacksToken == null) return null if (stacksToken == null) return null
if (!KnownChainId.isEVMChain(evmChain)) return null if (route.evmToken != null && !KnownTokenId.isEVMToken(route.evmToken)) {
if (!KnownTokenId.isEVMToken(evmToken)) return null return null
}
if (evmChain == null || !KnownChainId.isEVMChain(evmChain)) return null
return { return {
evmChain, evmChain,
evmToken, evmToken: route.evmToken ?? createEVMToken(evmChain, route.evmTokenAddress),
evmTokenAddress: route.evmTokenAddress,
stacksChain, stacksChain,
stacksToken, stacksToken,
proxyStacksTokenContractAddress: route.proxyStacksTokenContractAddress, proxyStacksTokenContractAddress: route.proxyStacksTokenContractAddress,
@@ -109,8 +117,9 @@ async function _getEVMSupportedRoutes(
return routes.filter(isNotNull) return routes.filter(isNotNull)
} }
interface SupportedEVMBridgeRoute { interface SupportedEVMBridgeRoute {
evmChain: string evmChainId: `${number}`
evmToken: string evmToken?: TokenId
evmTokenAddress: EVMAddress
stacksTokenContractAddress: StacksContractAddress stacksTokenContractAddress: StacksContractAddress
proxyStacksTokenContractAddress: null | StacksContractAddress proxyStacksTokenContractAddress: null | StacksContractAddress
pegOutFeeRate: `${number}` pegOutFeeRate: `${number}`

View File

@@ -1,24 +1,16 @@
import { Address, Client, isAddress, zeroAddress } from "viem" import { Address, Client } from "viem"
import { readContract } from "viem/actions"
import { BigNumber, BigNumberSource } from "../utils/BigNumber"
import {
KnownChainId,
KnownTokenId,
_allKnownEVMTokens,
} from "../utils/types/knownIds"
import { import {
EVMAddress, EVMAddress,
EVMNativeCurrencyAddress, EVMNativeCurrencyAddress,
evmNativeCurrencyAddress, evmNativeCurrencyAddress,
} from "../sdkUtils/types" } from "../sdkUtils/types"
import { SDKGlobalContext } from "../sdkUtils/types.internal" import { SDKGlobalContext } from "../sdkUtils/types.internal"
import { BridgeConfigAbi } from "./contractAbi/bridgeConfig" import { BigNumber, BigNumberSource } from "../utils/BigNumber"
import { import { KnownChainId, KnownTokenId } from "../utils/types/knownIds"
EVMEndpointContract,
EVMOnChainAddresses,
evmContractAddresses,
} from "./evmContractAddresses"
import { nativeCurrencyAddress } from "./addressHelpers" import { nativeCurrencyAddress } from "./addressHelpers"
import { getEVMOnChainConfig } from "./apiHelpers/getEVMOnChainConfig"
import { getEVMSupportedRoutes } from "./apiHelpers/getEVMSupportedRoutes"
import { EVMEndpointContract } from "./evmContractAddresses"
const CONTRACT_COMMON_NUMBER_SCALE = 18 const CONTRACT_COMMON_NUMBER_SCALE = 18
export const numberFromSolidityContractNumber = ( export const numberFromSolidityContractNumber = (
@@ -53,26 +45,23 @@ export async function getEVMContractCallInfo(
timeLockContractAddress?: Address timeLockContractAddress?: Address
} }
> { > {
const addresses = await getAllAddresses(sdkContext, chainId) const client = sdkContext.evm.viemClients[chainId]
if (addresses == null) return if (client == null) return
const config = await getEVMOnChainConfig(sdkContext, chainId)
if (config == null) return
const bridgeEndpointContractAddress = const bridgeEndpointContractAddress =
addresses.onChainAddresses?.[EVMEndpointContract.BridgeEndpoint] ?? config[EVMEndpointContract.BridgeEndpoint]
addresses.localAddresses[EVMEndpointContract.BridgeEndpoint]
if (bridgeEndpointContractAddress == null) return if (bridgeEndpointContractAddress == null) return
const nativeBridgeEndpointContractAddress = const nativeBridgeEndpointContractAddress =
addresses.onChainAddresses?.[EVMEndpointContract.NativeBridgeEndpoint] ?? config[EVMEndpointContract.NativeBridgeEndpoint]
addresses.localAddresses[EVMEndpointContract.NativeBridgeEndpoint] const registryContractAddress = config[EVMEndpointContract.Registry]
const registryContractAddress = const timeLockContractAddress = config[EVMEndpointContract.TimeLock]
addresses.onChainAddresses?.[EVMEndpointContract.Registry] ??
addresses.localAddresses[EVMEndpointContract.Registry]
const timeLockContractAddress =
addresses.onChainAddresses?.[EVMEndpointContract.TimeLock] ??
addresses.localAddresses[EVMEndpointContract.TimeLock]
return { return {
client: addresses.client, client,
bridgeEndpointContractAddress, bridgeEndpointContractAddress,
nativeBridgeEndpointContractAddress, nativeBridgeEndpointContractAddress,
registryContractAddress, registryContractAddress,
@@ -91,16 +80,19 @@ export async function getEVMTokenContractInfo(
tokenContractAddress: Address | EVMNativeCurrencyAddress tokenContractAddress: Address | EVMNativeCurrencyAddress
} }
> { > {
const addresses = await getAllAddresses(sdkContext, chainId) const client = sdkContext.evm.viemClients[chainId]
if (addresses == null) return if (client == null) return
const tokenContractAddress = const routes = await getEVMSupportedRoutes(sdkContext, chainId)
addresses.onChainAddresses?.[tokenId] ?? addresses.localAddresses[tokenId] if (routes == null) return
const tokenContractAddress = routes.find(
r => r.evmToken === tokenId,
)?.evmTokenAddress
if (tokenContractAddress == null) return if (tokenContractAddress == null) return
return { return {
client: addresses.client, client,
tokenContractAddress: tokenContractAddress:
tokenContractAddress === nativeCurrencyAddress tokenContractAddress === nativeCurrencyAddress
? evmNativeCurrencyAddress ? evmNativeCurrencyAddress
@@ -113,223 +105,11 @@ export async function getEVMToken(
chain: KnownChainId.EVMChain, chain: KnownChainId.EVMChain,
tokenAddress: EVMAddress, tokenAddress: EVMAddress,
): Promise<undefined | KnownTokenId.EVMToken> { ): Promise<undefined | KnownTokenId.EVMToken> {
const addresses = await getAllAddresses(sdkContext, chain) const routes = await getEVMSupportedRoutes(sdkContext, chain)
if (addresses == null) return if (routes == null) return
tokenAddress = tokenAddress.toLowerCase() as EVMAddress tokenAddress = tokenAddress.toLowerCase() as EVMAddress
return Object.values(_allKnownEVMTokens).find( return routes.find(
token => r => r.evmTokenAddress.toLowerCase() === tokenAddress.toLowerCase(),
( )?.evmToken
addresses.onChainAddresses?.[token] ?? addresses.localAddresses?.[token]
)?.toLowerCase() === tokenAddress,
)
}
export async function getAllAddresses(
sdkContext: SDKGlobalContext,
chainId: KnownChainId.EVMChain,
): Promise<
| undefined
| {
client: Client
onChainAddresses?: EVMOnChainAddresses
localAddresses: EVMOnChainAddresses
}
> {
const client = sdkContext.evm.viemClients[chainId]
const localAddresses = evmContractAddresses[chainId]
const configContractAddress = localAddresses[EVMEndpointContract.BridgeConfig]
if (client == null) return
let onChainAddresses: undefined | EVMOnChainAddresses
if (configContractAddress != null) {
onChainAddresses = await getOnChainConfigs(
sdkContext,
chainId,
configContractAddress,
)
}
return {
client,
onChainAddresses,
localAddresses,
}
}
const getOnChainConfigs = async (
sdkContext: SDKGlobalContext,
chain: KnownChainId.EVMChain,
configContractAddress: Address,
): Promise<undefined | EVMOnChainAddresses> => {
const cache = sdkContext.evm.onChainConfigCache
const cacheKey = `${chain}:${configContractAddress}` as const
if (cache != null) {
const cachedPromise = cache.get(cacheKey)
if (cachedPromise != null) return cachedPromise
}
const client = sdkContext.evm.viemClients[chain]
if (client == null) return
const promise = _getOnChainConfigsImpl(
client,
chain,
configContractAddress,
).catch(err => {
queueMicrotask(() => {
if (cache != null && promise === cache.get(cacheKey)) {
cache.delete(cacheKey)
}
})
throw err
})
if (cache != null) {
cache.set(cacheKey, promise)
}
return promise
}
const _getOnChainConfigsImpl = async (
client: Client,
chain: KnownChainId.EVMChain,
configContractAddress: Address,
): Promise<EVMOnChainAddresses> => {
const configs = await readContract(client, {
abi: BridgeConfigAbi,
address: configContractAddress,
functionName: "getConfigs",
args: [
[
ONCHAIN_CONFIG_KEY.ENDPOINT,
ONCHAIN_CONFIG_KEY.REGISTRY,
ONCHAIN_CONFIG_KEY.TIMELOCK,
ONCHAIN_CONFIG_KEY.ENDPOINT_NATIVE,
ONCHAIN_CONFIG_KEY.TOKEN_ABTC,
ONCHAIN_CONFIG_KEY.TOKEN_ALEX,
ONCHAIN_CONFIG_KEY.TOKEN_ATALEX,
ONCHAIN_CONFIG_KEY.TOKEN_LISTX,
ONCHAIN_CONFIG_KEY.TOKEN_USDT,
ONCHAIN_CONFIG_KEY.TOKEN_BTC,
ONCHAIN_CONFIG_KEY.TOKEN_LUNR,
ONCHAIN_CONFIG_KEY.TOKEN_SKO,
ONCHAIN_CONFIG_KEY.TOKEN_SUSDT,
ONCHAIN_CONFIG_KEY.TOKEN_UBTC,
ONCHAIN_CONFIG_KEY.TOKEN_WUBTC,
ONCHAIN_CONFIG_KEY.TOKEN_DB20,
ONCHAIN_CONFIG_KEY.TOKEN_DOG,
ONCHAIN_CONFIG_KEY.TOKEN_STX,
ONCHAIN_CONFIG_KEY.TOKEN_TRUMP,
ONCHAIN_CONFIG_KEY.TOKEN_GHIBLICZ,
ONCHAIN_CONFIG_KEY.TOKEN_ETH,
ONCHAIN_CONFIG_KEY.TOKEN_SOL,
ONCHAIN_CONFIG_KEY.TOKEN_LINK,
],
],
}).catch(err => {
console.groupCollapsed(
`Failed to read on-chain configs from ${configContractAddress} (${chain})`,
)
console.error(err)
console.groupEnd()
return null
})
if (configs == null) {
return {}
}
const EVMToken = KnownTokenId.EVM
return {
[EVMEndpointContract.BridgeEndpoint]: maybeAddress(configs[0]),
[EVMEndpointContract.Registry]: maybeAddress(configs[1]),
[EVMEndpointContract.TimeLock]: maybeAddress(configs[2]),
[EVMEndpointContract.NativeBridgeEndpoint]: maybeAddress(configs[3]),
[EVMToken.aBTC]: maybeAddress(configs[4]),
[EVMToken.ALEX]: maybeAddress(configs[5]),
[EVMToken.vLiALEX]: maybeAddress(configs[6]),
[EVMToken.vLiSTX]: maybeAddress(configs[7]),
// prettier-ignore
[EVMToken.USDT]:
chain === KnownChainId.EVM.Ethereum ||
chain === KnownChainId.EVM.BSC
? maybeAddress(configs[8])
: undefined,
// prettier-ignore
[EVMToken.USDC]:
chain === KnownChainId.EVM.Base ||
chain === KnownChainId.EVM.Arbitrum
? maybeAddress(configs[8])
: undefined,
// prettier-ignore
[EVMToken.WBTC]:
chain === KnownChainId.EVM.Ethereum ||
chain === KnownChainId.EVM.Arbitrum
? maybeAddress(configs[9])
: undefined,
// prettier-ignore
[EVMToken.BTCB]:
chain === KnownChainId.EVM.BSC
? maybeAddress(configs[9])
: undefined,
// prettier-ignore
[EVMToken.cbBTC]:
chain === KnownChainId.EVM.Base
? maybeAddress(configs[9])
: undefined,
[EVMToken.LUNR]: maybeAddress(configs[10]),
[EVMToken.SKO]: maybeAddress(configs[11]),
[EVMToken.sUSDT]: maybeAddress(configs[12]),
[EVMToken.uBTC]: maybeAddress(configs[13]),
[EVMToken.wuBTC]: maybeAddress(configs[14]),
[EVMToken.DB20]: maybeAddress(configs[15]),
[EVMToken.DOG]: maybeAddress(configs[16]),
[EVMToken.STX]: maybeAddress(configs[17]),
[EVMToken.TRUMP]: maybeAddress(configs[18]),
[EVMToken.GHIBLICZ]: maybeAddress(configs[19]),
[EVMToken.ETH]: maybeAddress(configs[20]),
[EVMToken.SOL]: maybeAddress(configs[21]),
[EVMToken.LINK]: maybeAddress(configs[22]),
}
}
function maybeAddress(value: string | null): Address | undefined {
if (value == null) return undefined
if (value === "") return undefined
if (!isAddress(value)) return undefined
if (value === zeroAddress) return undefined
return value
}
enum ONCHAIN_CONFIG_KEY {
ENDPOINT = "ENDPOINT",
ENDPOINT_NATIVE = "ENDPOINT_NATIVE",
REGISTRY = "REGISTRY",
TIMELOCK = "TIMELOCK",
MULTISIG = "MULTISIG",
MIGRATE = "MIGRATE",
MIGRATE_BOB = "MIGRATE_BOB",
MIGRATE_BOB_L2 = "MIGRATE_BOB_L2",
MIGRATE_BOB_L2_S = "MIGRATE_BOB_L2_S",
TOKEN_ABTC = "TOKEN_ABTC",
TOKEN_ALEX = "TOKEN_ALEX",
TOKEN_ATALEX = "TOKEN_ATALEX",
TOKEN_LISTX = "TOKEN_LISTX",
TOKEN_USDT = "TOKEN_USDT",
TOKEN_BTC = "TOKEN_BTC",
TOKEN_LUNR = "TOKEN_LUNR",
TOKEN_SKO = "TOKEN_SKO",
TOKEN_SUSDT = "TOKEN_SUSDT",
TOKEN_DB20 = "TOKEN_DB20",
TOKEN_DOG = "TOKEN_DOG",
TOKEN_UBTC = "TOKEN_UBTC",
TOKEN_WUBTC = "TOKEN_WUBTC",
TOKEN_STX = "TOKEN_STX",
TOKEN_TRUMP = "TOKEN_TRUMP",
TOKEN_GHIBLICZ = "TOKEN_GHIBLICZ",
TOKEN_ETH = "TOKEN_ETH",
TOKEN_SOL = "TOKEN_SOL",
TOKEN_LINK = "TOKEN_LINK",
} }

View File

@@ -24,10 +24,12 @@ import {
lorenzo, lorenzo,
xLayer, xLayer,
} from "./evmChainInfos" } from "./evmChainInfos"
import { EVMChain } from "./evmContractAddresses"
import { KnownChainId } from "../utils/types/knownIds" import { KnownChainId } from "../utils/types/knownIds"
import { entries } from "../utils/objectHelper" import { entries } from "../utils/objectHelper"
type EVMChain = KnownChainId.EVMChain
const EVMChain = KnownChainId.EVM
export const defaultEvmClients: Partial<Record<KnownChainId.EVMChain, Client>> = export const defaultEvmClients: Partial<Record<KnownChainId.EVMChain, Client>> =
{ {
[EVMChain.Ethereum]: createClient({ [EVMChain.Ethereum]: createClient({

View File

@@ -1,13 +1,7 @@
import { Address } from "viem"
import { KnownChainId, KnownTokenId } from "../utils/types/knownIds"
import { nativeCurrencyAddress } from "./addressHelpers"
export type EVMChain = KnownChainId.EVMChain
export const EVMChain = KnownChainId.EVM
type EVMToken = KnownTokenId.EVMToken
const EVMToken = KnownTokenId.EVM
/**
* source: https://github.com/alexgo-io/alex-app/blob/3d842513272ba7478dcd6512bae9fa8d883d2cc5/functions/_handlers/services/getEVMOnChainConfig.evmAddressHelpers.ts#L5-L17
*/
export type EVMEndpointContract = export type EVMEndpointContract =
| typeof EVMEndpointContract.BridgeEndpoint | typeof EVMEndpointContract.BridgeEndpoint
| typeof EVMEndpointContract.NativeBridgeEndpoint | typeof EVMEndpointContract.NativeBridgeEndpoint
@@ -21,129 +15,3 @@ export namespace EVMEndpointContract {
export const TimeLock = "TimeLock" export const TimeLock = "TimeLock"
export const Registry = "Registry" export const Registry = "Registry"
} }
export type EVMOnChainAddresses = Partial<
Record<EVMEndpointContract | EVMToken, Address>
>
export const evmContractAddresses: Record<EVMChain, EVMOnChainAddresses> = {
[EVMChain.Ethereum]: {
// https://t.me/c/1599543687/57297
[EVMEndpointContract.BridgeConfig]:
"0x79d1C91053baceced5C796aB8a765E4d5aB38e8a",
},
[EVMChain.BSC]: {
// https://t.me/c/1599543687/57297
[EVMEndpointContract.BridgeConfig]:
"0x7062dB5dcaECDb355878a0BAB00A6941345D8711",
},
[EVMChain.CoreDAO]: {
// https://t.me/c/1599543687/57297
[EVMEndpointContract.BridgeConfig]:
"0x7062dB5dcaECDb355878a0BAB00A6941345D8711",
},
[EVMChain.Bsquared]: {
// https://t.me/c/1599543687/57297
[EVMEndpointContract.BridgeConfig]:
"0xf99f62475F50BE59393dbdc148E6627E4E88Fc24",
},
[EVMChain.BOB]: {
// https://t.me/c/1599543687/57297
[EVMEndpointContract.BridgeConfig]:
"0xf99f62475F50BE59393dbdc148E6627E4E88Fc24",
},
[EVMChain.Bitlayer]: {
// https://t.me/c/1599543687/57297
[EVMEndpointContract.BridgeConfig]:
"0xf99f62475F50BE59393dbdc148E6627E4E88Fc24",
},
[EVMChain.Lorenzo]: {
// https://t.me/c/1599543687/57297
[EVMEndpointContract.BridgeConfig]:
"0xf99f62475F50BE59393dbdc148E6627E4E88Fc24",
},
[EVMChain.Merlin]: {
// https://t.me/c/1599543687/57297
[EVMEndpointContract.BridgeConfig]:
"0xf99f62475F50BE59393dbdc148E6627E4E88Fc24",
},
[EVMChain.AILayer]: {
// https://t.me/c/1599543687/57439
[EVMEndpointContract.BridgeConfig]:
"0xf99f62475F50BE59393dbdc148E6627E4E88Fc24",
},
[EVMChain.Mode]: {
// https://t.me/c/1599543687/57779
[EVMEndpointContract.BridgeConfig]:
"0xf99f62475F50BE59393dbdc148E6627E4E88Fc24",
},
[EVMChain.XLayer]: {
// https://t.me/c/1599543687/58186
[EVMEndpointContract.BridgeConfig]:
"0xf99f62475F50BE59393dbdc148E6627E4E88Fc24",
},
[EVMChain.Arbitrum]: {
// https://t.me/c/1599543687/58824
[EVMEndpointContract.BridgeConfig]:
"0xf99f62475F50BE59393dbdc148E6627E4E88Fc24",
},
[EVMChain.Aurora]: {
// https://t.me/c/1599543687/59145
[EVMEndpointContract.BridgeConfig]:
"0xf99f62475F50BE59393dbdc148E6627E4E88Fc24",
},
[EVMChain.Manta]: {
// https://t.me/c/1599543687/60487
[EVMEndpointContract.BridgeConfig]:
"0xf99f62475F50BE59393dbdc148E6627E4E88Fc24",
},
[EVMChain.Linea]: {
// https://t.me/c/1599543687/61611
// https://t.me/c/1599543687/61873
// https://t.me/c/1599543687/61734
[EVMEndpointContract.BridgeConfig]:
"0xf99f62475F50BE59393dbdc148E6627E4E88Fc24",
},
[EVMChain.Base]: {
// https://t.me/c/1599543687/64684
[EVMEndpointContract.BridgeConfig]:
"0xf99f62475F50BE59393dbdc148E6627E4E88Fc24",
},
// testnet
[EVMChain.Sepolia]: {
[EVMEndpointContract.BridgeConfig]:
"0xE76e9e28ab8f7974F8bA24e4d83f9550BFe08d21",
},
[EVMChain.BSCTestnet]: {},
[EVMChain.CoreDAOTestnet]: {
[EVMEndpointContract.BridgeConfig]:
"0xdbe8BBA9C95140bc4F5e3480Fe6a958Cd1C7E6CC",
},
[EVMChain.BlifeTestnet]: {
[EVMEndpointContract.BridgeConfig]:
"0x643F9D448BC0F8D365bd0DbEEcB5BC6A7b96d922",
[EVMToken.WBTC]: nativeCurrencyAddress,
},
[EVMChain.BitboyTestnet]: {
[EVMEndpointContract.BridgeEndpoint]:
"0x3114671EefE856B32851DF4bc5b6278d5A74b86b",
[EVMToken.sUSDT]: "0x0d05e721F127AF25bDa0FE8836F1A2127028ad01",
[EVMToken.aBTC]: "0xEf33A9Afa67bad73b8df4beBD4C5Adc678D70528",
[EVMToken.ALEX]: "0x1DcD5BE312cc70c1e86218D2aC86EDDf79a851E4",
},
[EVMChain.BeraTestnet]: {
// https://t.me/c/1599543687/60509
// [EVMEndpointContract.BridgeConfig]:
// "0xBa175fDaB00e7FCF603f43bE8f68dB7f4de9f3A9",
// https://t.me/c/1599543687/60499
[EVMEndpointContract.Registry]:
"0x6c74Bc8c54114b8Fed89686cC345eBCd838Fa0b9",
[EVMToken.aBTC]: "0xD66FEeb23463f99f56363a7de7acEd7d04F3356e",
[EVMToken.ALEX]: "0x3114671EefE856B32851DF4bc5b6278d5A74b86b",
[EVMToken.vLiALEX]: "0x8EcfD0a81c2965d16b78e86b8E4Dc71D0109e0e1",
[EVMToken.vLiSTX]: "0x2e3149230f98e7474AAAB3c1F6323BADfC4A66F8",
[EVMToken.sUSDT]: "0x8F4eB4dB1493D800Bf476137A25dC3c3cD58952C",
[EVMToken.wuBTC]: "0x391c193a3268aA0A93D76EAc85B88985b5CB92da",
},
}

View File

@@ -1,6 +1,6 @@
import { Client } from "viem" import { Client } from "viem"
import { EVMOnChainConfigByEVMChain } from "../evmUtils/apiHelpers/getEVMOnChainConfig"
import { EVMSupportedRoute } from "../evmUtils/apiHelpers/getEVMSupportedRoutes" import { EVMSupportedRoute } from "../evmUtils/apiHelpers/getEVMSupportedRoutes"
import { EVMOnChainAddresses } from "../evmUtils/evmContractAddresses"
import type { BRC20SupportedRoute } from "../metaUtils/apiHelpers/getBRC20SupportedRoutes" import type { BRC20SupportedRoute } from "../metaUtils/apiHelpers/getBRC20SupportedRoutes"
import type { RunesSupportedRoute } from "../metaUtils/apiHelpers/getRunesSupportedRoutes" import type { RunesSupportedRoute } from "../metaUtils/apiHelpers/getRunesSupportedRoutes"
import { StacksTokenInfo } from "../stacksUtils/apiHelpers/getAllStacksTokens" import { StacksTokenInfo } from "../stacksUtils/apiHelpers/getAllStacksTokens"
@@ -9,7 +9,6 @@ import { pMemoizeImpl } from "../utils/pMemoize"
import { GeneralCacheInterface } from "../utils/types/GeneralCacheInterface" import { GeneralCacheInterface } from "../utils/types/GeneralCacheInterface"
import { KnownChainId } from "../utils/types/knownIds" import { KnownChainId } from "../utils/types/knownIds"
import { TransferProphet } from "../utils/types/TransferProphet" import { TransferProphet } from "../utils/types/TransferProphet"
import { EVMAddress } from "./types"
export interface SDKGlobalContextCache<K, V> export interface SDKGlobalContextCache<K, V>
extends GeneralCacheInterface<K, V> {} extends GeneralCacheInterface<K, V> {}
@@ -82,8 +81,8 @@ export interface SDKGlobalContext {
Promise<EVMSupportedRoute[]> Promise<EVMSupportedRoute[]>
> >
onChainConfigCache?: SDKGlobalContextCache< onChainConfigCache?: SDKGlobalContextCache<
`${KnownChainId.EVMChain}:${EVMAddress}`, "mainnet" | "testnet",
Promise<EVMOnChainAddresses> Promise<EVMOnChainConfigByEVMChain>
> >
viemClients: Partial<Record<KnownChainId.EVMChain, Client>> viemClients: Partial<Record<KnownChainId.EVMChain, Client>>
} }

View File

@@ -1,9 +1,36 @@
import { ChainId, RuneIdCombined, TokenId } from "../../sdkUtils/types" import {
ChainId,
EVMAddress,
RuneIdCombined,
TokenId,
} from "../../sdkUtils/types"
import { checkNever } from "../typeHelpers" import { checkNever } from "../typeHelpers"
const chainId = <const T extends string>(value: T): ChainId<T> => value as any const chainId = <const T extends string>(value: T): ChainId<T> => value as any
const tokenId = <const T extends string>(value: T): TokenId<T> => value as any const tokenId = <const T extends string>(value: T): TokenId<T> => value as any
export const createStacksToken = (
stacksTokenId: string,
): KnownTokenId.StacksToken => {
return `stx-token-${stacksTokenId}` as any
}
export const createBRC20Token = (
brc20tick: string,
): KnownTokenId.BRC20Token => {
return `brc20-token-${brc20tick}` as any
}
export const createRunesToken = (
runeId: RuneIdCombined,
): KnownTokenId.RunesToken => {
return `runes-token-${runeId}` as any
}
export const createEVMToken = (
evmChain: KnownChainId.EVMChain,
evmTokenAddress: EVMAddress,
): KnownTokenId.EVMToken => {
return `evm-token-${evmTokenAddress}(${evmChain})` as any
}
/** /**
* The `KnownTokenId` namespace provides types of tokens supported by the SDK, * The `KnownTokenId` namespace provides types of tokens supported by the SDK,
* including Bitcoin, EVM-compatible tokens, and Stacks tokens. * including Bitcoin, EVM-compatible tokens, and Stacks tokens.
@@ -29,7 +56,7 @@ export namespace KnownTokenId {
/** A namespace that contains constants and types for Bitcoin tokens. */ /** A namespace that contains constants and types for Bitcoin tokens. */
export namespace Bitcoin { export namespace Bitcoin {
/** Represents the Bitcoin token ID (BTC). */ /** Represents the Bitcoin token ID (BTC). */
export const BTC = tokenId("btc-btc") export const BTC = tokenId("btc-token-btc")
} }
/** This type defines known Bitcoin tokens. */ /** This type defines known Bitcoin tokens. */
export type BitcoinToken = (typeof _allKnownBitcoinTokens)[number] export type BitcoinToken = (typeof _allKnownBitcoinTokens)[number]
@@ -40,144 +67,115 @@ export namespace KnownTokenId {
/** This type defines known BRC20 tokens. */ /** This type defines known BRC20 tokens. */
export type BRC20Token = TokenId<"a brc20 token"> export type BRC20Token = TokenId<"a brc20 token">
export function isBRC20Token(value: TokenId): value is BRC20Token { export function isBRC20Token(value: TokenId): value is BRC20Token {
return value.startsWith("brc20-") return value.startsWith("brc20-token-")
} }
/** This type defines known Runes tokens. */ /** This type defines known Runes tokens. */
export type RunesToken = TokenId<"a runes token"> export type RunesToken = TokenId<"a runes token">
export function isRunesToken(value: TokenId): value is RunesToken { export function isRunesToken(value: TokenId): value is RunesToken {
return value.startsWith("runes-") return value.startsWith("runes-token-")
} }
/** A namespace that contains constants and types for EVM-compatible tokens. */ /** A namespace that contains constants and types for EVM-compatible tokens. */
export namespace EVM { export namespace EVM {
// USD[X]s // USD[X]s
/** Represents the sUSDT token ID on EVM-compatible blockchains. */ /** Represents the sUSDT token ID on EVM-compatible blockchains. */
export const sUSDT = tokenId("evm-susdt") export const sUSDT = tokenId("evm-token-susdt")
/** Represents the USDT token ID on EVM-compatible blockchains. */ /** Represents the USDT token ID on EVM-compatible blockchains. */
export const USDT = tokenId("evm-usdt") export const USDT = tokenId("evm-token-usdt")
/** Represents the USDC token ID on EVM-compatible blockchains. */ /** Represents the USDC token ID on EVM-compatible blockchains. */
export const USDC = tokenId("evm-usdc") export const USDC = tokenId("evm-token-usdc")
// BTC // BTC
/** Represents the aBTC token ID on EVM-compatible blockchains. */ /** Represents the aBTC token ID on EVM-compatible blockchains. */
export const aBTC = tokenId("evm-abtc") export const aBTC = tokenId("evm-token-abtc")
/** Represents the WBTC token ID on EVM-compatible blockchains. */ /** Represents the WBTC token ID on EVM-compatible blockchains. */
export const WBTC = tokenId("evm-wbtc") export const WBTC = tokenId("evm-token-wbtc")
/** Represents the BTCB token ID on EVM-compatible blockchains. */ /** Represents the BTCB token ID on EVM-compatible blockchains. */
export const BTCB = tokenId("evm-btcb") export const BTCB = tokenId("evm-token-btcb")
/** Represents the cbBTC token ID on EVM-compatible blockchains. */ /** Represents the cbBTC token ID on EVM-compatible blockchains. */
export const cbBTC = tokenId("evm-cbbtc") export const cbBTC = tokenId("evm-token-cbbtc")
/** Represents the LUNR token ID on EVM-compatible blockchains. */ /** Represents the LUNR token ID on EVM-compatible blockchains. */
export const LUNR = tokenId("evm-lunr") export const LUNR = tokenId("evm-token-lunr")
/** Represents the ALEX token ID on EVM-compatible blockchains. */ /** Represents the ALEX token ID on EVM-compatible blockchains. */
export const ALEX = tokenId("evm-alex") export const ALEX = tokenId("evm-token-alex")
/** Represents the SKO token ID on EVM-compatible blockchains. */ /** Represents the SKO token ID on EVM-compatible blockchains. */
export const SKO = tokenId("evm-sko") export const SKO = tokenId("evm-token-sko")
/** Represents the vLiSTX token ID on EVM-compatible blockchains. */ /** Represents the vLiSTX token ID on EVM-compatible blockchains. */
export const vLiSTX = tokenId("evm-vlistx") export const vLiSTX = tokenId("evm-token-vlistx")
/** Represents the vLiALEX token ID on EVM-compatible blockchains. */ /** Represents the vLiALEX token ID on EVM-compatible blockchains. */
export const vLiALEX = tokenId("evm-vlialex") export const vLiALEX = tokenId("evm-token-vlialex")
/** Represents the uBTC token ID on EVM-compatible blockchains. */ /** Represents the uBTC token ID on EVM-compatible blockchains. */
export const uBTC = tokenId("evm-ubtc") export const uBTC = tokenId("evm-token-ubtc")
/** Represents the wuBTC token ID on EVM-compatible blockchains. */ /** Represents the wuBTC token ID on EVM-compatible blockchains. */
export const wuBTC = tokenId("evm-wubtc") export const wuBTC = tokenId("evm-token-wubtc")
/** Represents the DB20 token ID on EVM-compatible blockchains. */ /** Represents the DB20 token ID on EVM-compatible blockchains. */
export const DB20 = tokenId("evm-db20") export const DB20 = tokenId("evm-token-db20")
/** Represents the DOG token ID on EVM-compatible blockchains. */ /** Represents the DOG token ID on EVM-compatible blockchains. */
export const DOG = tokenId("evm-dog") export const DOG = tokenId("evm-token-dog")
/** Represents the STX token ID on EVM-compatible blockchains. */ /** Represents the STX token ID on EVM-compatible blockchains. */
export const STX = tokenId("evm-stx") export const STX = tokenId("evm-token-stx")
/** Represents the TRUMP token ID on EVM-compatible blockchains. */ /** Represents the TRUMP token ID on EVM-compatible blockchains. */
export const TRUMP = tokenId("evm-trump") export const TRUMP = tokenId("evm-token-trump")
export const GHIBLICZ = tokenId("evm-ghiblicz") export const GHIBLICZ = tokenId("evm-token-ghiblicz")
export const ETH = tokenId("evm-eth") export const ETH = tokenId("evm-token-eth")
export const SOL = tokenId("evm-sol") export const SOL = tokenId("evm-token-sol")
export const LINK = tokenId("evm-link") export const LINK = tokenId("evm-token-link")
} }
/** This type defines known tokens on EVM-compatible blockchains. */ /** This type includes all known tokens on EVM-compatible blockchains. */
export type EVMToken = (typeof _allKnownEVMTokens)[number] export type EVMToken =
| TokenId<`a EVM token`>
| (typeof _allKnownEVMTokens)[number]
export function isEVMToken(value: TokenId): value is EVMToken { export function isEVMToken(value: TokenId): value is EVMToken {
return _allKnownEVMTokens.includes(value as any) return value.startsWith("evm-token-")
} }
/** A namespace that contains constants and types for Stacks tokens. */ /** A namespace that contains constants and types for Stacks tokens. */
export namespace Stacks { export namespace Stacks {
/** Represents the sUSDT token ID on the Stacks blockchain. */ /** Represents the sUSDT token ID on the Stacks blockchain. */
export const sUSDT = tokenId("stx-susdt") export const sUSDT = tokenId("stx-token-susdt")
/** Represents the sLUNR token ID on the Stacks blockchain. */ /** Represents the sLUNR token ID on the Stacks blockchain. */
export const sLUNR = tokenId("stx-slunr") export const sLUNR = tokenId("stx-token-slunr")
/** Represents the aBTC token ID on the Stacks blockchain. */ /** Represents the aBTC token ID on the Stacks blockchain. */
export const aBTC = tokenId("stx-abtc") export const aBTC = tokenId("stx-token-abtc")
/** Represents the ALEX token ID on the Stacks blockchain. */ /** Represents the ALEX token ID on the Stacks blockchain. */
export const ALEX = tokenId("stx-alex") export const ALEX = tokenId("stx-token-alex")
/** Represents the sSKO token ID on the Stacks blockchain. */ /** Represents the sSKO token ID on the Stacks blockchain. */
export const sSKO = tokenId("stx-ssko") export const sSKO = tokenId("stx-token-ssko")
/** Represents the vLiSTX token ID on the Stacks blockchain. */ /** Represents the vLiSTX token ID on the Stacks blockchain. */
export const vLiSTX = tokenId("stx-vlistx") export const vLiSTX = tokenId("stx-token-vlistx")
/** Represents the vLiALEX token ID on the Stacks blockchain. */ /** Represents the vLiALEX token ID on the Stacks blockchain. */
export const vLiALEX = tokenId("stx-vlialex") export const vLiALEX = tokenId("stx-token-vlialex")
/** Represents the vLiaBTC token ID on the Stacks blockchain. */ /** Represents the vLiaBTC token ID on the Stacks blockchain. */
export const vLiaBTC = tokenId("stx-vliabtc") export const vLiaBTC = tokenId("stx-token-vliabtc")
/** Represents the DB20 token ID on the Stacks blockchain. */ /** Represents the DB20 token ID on the Stacks blockchain. */
export const DB20 = tokenId("stx-db20") export const DB20 = tokenId("stx-token-db20")
/** Represents the uBTC token ID on the Stacks blockchain. */ /** Represents the uBTC token ID on the Stacks blockchain. */
export const uBTC = tokenId("stx-ubtc") export const uBTC = tokenId("stx-token-ubtc")
/** Represents the DOG token ID on the Stacks blockchain. */ /** Represents the DOG token ID on the Stacks blockchain. */
export const DOG = tokenId("stx-dog") export const DOG = tokenId("stx-token-dog")
/** Represents the STX token ID on the Stacks blockchain. */ /** Represents the STX token ID on the Stacks blockchain. */
export const STX = tokenId("stx-stx") export const STX = tokenId("stx-token-stx")
/** Represents the TRUMP token ID on the Stacks blockchain. */ /** Represents the TRUMP token ID on the Stacks blockchain. */
export const TRUMP = tokenId("stx-trump") export const TRUMP = tokenId("stx-token-trump")
export const GHIBLICZ = tokenId("stx-ghiblicz") export const GHIBLICZ = tokenId("stx-token-ghiblicz")
export const ETH = tokenId("stx-eth") export const ETH = tokenId("stx-token-eth")
export const SOL = tokenId("stx-sol") export const SOL = tokenId("stx-token-sol")
export const LINK = tokenId("stx-link") export const LINK = tokenId("stx-token-link")
} }
const _allKnownStacksTokens = [
Stacks.sUSDT,
Stacks.sLUNR,
Stacks.aBTC,
Stacks.ALEX,
Stacks.sSKO,
Stacks.vLiSTX,
Stacks.vLiALEX,
Stacks.vLiaBTC,
Stacks.DB20,
Stacks.uBTC,
Stacks.DOG,
Stacks.STX,
Stacks.TRUMP,
Stacks.GHIBLICZ,
Stacks.ETH,
Stacks.SOL,
Stacks.LINK,
] as const
export type StacksToken = export type StacksToken =
| TokenId<`a Stacks token`> | TokenId<`a Stacks token`>
| (typeof _allKnownStacksTokens)[number] | (typeof _allKnownStacksTokens)[number]
export function isStacksToken(value: TokenId): value is StacksToken { export function isStacksToken(value: TokenId): value is StacksToken {
return value.startsWith("stx-") return value.startsWith("stx-token-")
} }
} }
export const createStacksToken = (
stacksTokenId: string,
): KnownTokenId.StacksToken => {
return `stx-${stacksTokenId}` as any
}
export const createBRC20Token = (
brc20tick: string,
): KnownTokenId.BRC20Token => {
return `brc20-${brc20tick}` as any
}
export const createRunesToken = (
runeId: RuneIdCombined,
): KnownTokenId.RunesToken => {
return `runes-${runeId}` as any
}
export const _allKnownBitcoinTokens = Object.values(KnownTokenId.Bitcoin) export const _allKnownBitcoinTokens = Object.values(KnownTokenId.Bitcoin)
export const _allKnownStacksTokens = Object.values(KnownTokenId.Stacks)
export const _allKnownEVMTokens = Object.values(KnownTokenId.EVM) export const _allKnownEVMTokens = Object.values(KnownTokenId.EVM)
/** /**

View File

@@ -4,7 +4,8 @@
"node_modules", "node_modules",
"lib", "lib",
"examples/cross-chain-swap", "examples/cross-chain-swap",
"examples/bridgeFrom" "examples/bridgeFrom",
"generated/docs"
], ],
"compilerOptions": { "compilerOptions": {
"module": "esnext", "module": "esnext",