feat: add ETH token support

This commit is contained in:
c4605
2025-04-04 16:13:28 +02:00
parent 5ce224b37b
commit c6c77f1bab
4 changed files with 195 additions and 0 deletions

View File

@@ -0,0 +1,178 @@
# How to Add Support for a new EVM Token
This document explains the process for adding support for a new EVM token in the XLink SDK.
## Overview
Adding support for a new EVM token requires modifying the following files:
1. `src/utils/types/knownIds.ts` - Add the new Token ID
2. `src/evmUtils/xlinkContractHelpers.ts` - Add the token to the contract configuration
3. `src/stacksUtils/stxContractAddresses.ts` - Add contract addresses for the corresponding token on the Stacks chain
## Important Notice for Developers and AI Assistants
**CRITICAL**: The following values MUST be obtained from contract deployers or development team and should NEVER be generated by developers or AI tools:
1. The exact `ONCHAIN_CONFIG_KEY` value for the token (e.g., `TOKEN_NEW_TOKEN`)
2. The contract addresses in `stxTokenContractAddresses_legacy`
3. The token name/identifier (the actual token name like "ETH", "BTC", etc.)
These values are determined by the contract deployers and must match the deployed contract configurations.
**NAMING CONVENTIONS**:
- `KnownTokenId.EVM.TOKEN_NAME` and `KnownTokenId.Stacks.TOKEN_NAME` typically use the same name (e.g., both would be "ETH" for ETH)
- However, `ONCHAIN_CONFIG_KEY.TOKEN_NAME` is NOT directly related to these names and is determined by how it's defined in the smart contract (e.g., "TOKEN_ETH" for ETH)
- Always confirm the exact naming for `ONCHAIN_CONFIG_KEY` with the contract deployers, as it must match what's in the contract
## Detailed Steps
### 1. Add the Token ID in knownIds.ts
In the `src/utils/types/knownIds.ts` file, add the new Token ID to the appropriate sections in the `KnownTokenId` namespace:
```typescript
export namespace KnownTokenId {
export namespace EVM {
// Add the new EVM Token ID here - use the exact token name provided by the team
// For example, ETH for Ethereum
export const TOKEN_NAME = tokenId("evm-tokenname")
}
// If Stacks support is needed, also add it to the Stacks namespace
// Use the same token name as above
export namespace Stacks {
export const TOKEN_NAME = tokenId("stx-tokenname")
}
}
```
### 2. Update Contract Configuration in xlinkContractHelpers.ts
In the `src/evmUtils/xlinkContractHelpers.ts` file, you need to update the following sections:
1. Add a new token key to the `ONCHAIN_CONFIG_KEY` enum:
```typescript
enum ONCHAIN_CONFIG_KEY {
// Other token keys...
// IMPORTANT: Use the exact key provided by the contract deployers
// This key format is usually different from the token name itself
// For example, TOKEN_ETH for Ethereum
TOKEN_KEY = "TOKEN_KEY", // This must match what's configured in the smart contract
}
```
2. Add the new token key to the `getConfigs` call in the `_getOnChainConfigsImpl` function:
```typescript
const configs = await readContract(client, {
abi: BridgeConfigAbi,
address: configContractAddress,
functionName: "getConfigs",
args: [
[
// Other token keys...
ONCHAIN_CONFIG_KEY.TOKEN_KEY, // Use the key added in the enum above
],
],
})
```
3. Add the token mapping to the return object in the same function:
```typescript
return {
// Other mappings...
// Note: EVMToken.TOKEN_NAME uses the same name as in KnownTokenId.EVM
// while ONCHAIN_CONFIG_KEY.TOKEN_KEY uses the contract-specific key
[EVMToken.TOKEN_NAME]: maybeAddress(configs[INDEX_POSITION]),
}
```
> Important: The `INDEX_POSITION` should match the position of your token key in the `getConfigs` args array. For example, if your token is the 21st item in the array, use `configs[20]` (zero-indexed).
### 3. Add Stacks Contract Addresses in stxContractAddresses.ts
Add the corresponding contract addresses in the `src/stacksUtils/stxContractAddresses.ts` file:
```typescript
export const stxTokenContractAddresses_legacy: Record<
// ...
> = {
// Other tokens...
// Use the same token name as in KnownTokenId.Stacks
[KnownTokenId.Stacks.TOKEN_NAME]: {
[KnownChainId.Stacks.Mainnet]: wrapContractAddress("mainnet", {
// IMPORTANT: Use the exact addresses provided by the contract deployers
deployerAddress: xlinkContractsMultisigMainnet,
contractName: "token-name", // This contract name must be obtained from the team
}),
[KnownChainId.Stacks.Testnet]: wrapContractAddress("testnet", {
// IMPORTANT: Use the exact addresses provided by the contract deployers
deployerAddress: xlinkContractsMultisigTestnet,
contractName: "token-name", // This contract name must be obtained from the team
}),
},
}
```
## Example: Adding ETH Token Support
Here's a real example of adding support for the ETH token:
1. Adding to `knownIds.ts`:
```typescript
export const ETH = tokenId("evm-eth") // In EVM namespace
export const ETH = tokenId("stx-eth") // In Stacks namespace - same name as EVM
```
2. Updating `xlinkContractHelpers.ts`:
```typescript
// Add to enum - this key was provided by the contract deployers
// Note that this is TOKEN_ETH, not just ETH
enum ONCHAIN_CONFIG_KEY {
// ...other tokens
TOKEN_ETH = "TOKEN_ETH",
}
// Add to getConfigs call
ONCHAIN_CONFIG_KEY.TOKEN_ETH,
// Add to return object mapping
// Here we use EVMToken.ETH (the token name), not TOKEN_ETH
[EVMToken.ETH]: maybeAddress(configs[20]),
```
3. Adding to `stxContractAddresses.ts`:
```typescript
[KnownTokenId.Stacks.ETH]: {
[KnownChainId.Stacks.Mainnet]: wrapContractAddress("mainnet", {
deployerAddress: xlinkContractsMultisigMainnet,
contractName: "token-eth", // This name was provided by the team
}),
[KnownChainId.Stacks.Testnet]: wrapContractAddress("testnet", {
deployerAddress: xlinkContractsMultisigTestnet,
contractName: "token-eth", // This name was provided by the team
}),
},
```
## Important Considerations
1. After adding a new token, ensure that all related cross-chain routing and validation logic works correctly
2. Maintain consistency with array indices - ensure the index position in the `configs` array matches the position of your token in the `getConfigs` args array
3. If the contract address is read from on-chain configuration, make sure the on-chain contract has the correct token address configured
4. After adding a new token, perform comprehensive testing to ensure all functionality works as expected
## For Automated Tools (AI Assistants)
When adding a new token, follow these exact steps:
1. **DO NOT generate any values on your own** - always ask for the official token name, ONCHAIN_CONFIG_KEY, and contract addresses
2. Identify the next available index position for the token in the `getConfigs` call
3. Add the token ID with the appropriate prefix pattern (e.g., "evm-tokenname" and "stx-tokenname")
4. Add the token to all three files mentioned above
5. Ensure the index position in the return mapping matches the position in the args array
6. Follow the existing naming conventions for contract names as specified by the contract deployers
7. Remember that KnownTokenId names typically match in EVM and Stacks namespaces, but ONCHAIN_CONFIG_KEY uses a different format defined by the contract

View File

@@ -223,6 +223,7 @@ const _getOnChainConfigsImpl = async (
ONCHAIN_CONFIG_KEY.TOKEN_STX,
ONCHAIN_CONFIG_KEY.TOKEN_TRUMP,
ONCHAIN_CONFIG_KEY.TOKEN_GHIBLICZ,
ONCHAIN_CONFIG_KEY.TOKEN_ETH,
],
],
}).catch(err => {
@@ -270,6 +271,7 @@ const _getOnChainConfigsImpl = async (
[EVMToken.STX]: maybeAddress(configs[17]),
[EVMToken.TRUMP]: maybeAddress(configs[18]),
[EVMToken.GHIBLICZ]: maybeAddress(configs[19]),
[EVMToken.ETH]: maybeAddress(configs[20]),
}
}
function maybeAddress(value: string | null): Address | undefined {
@@ -319,4 +321,7 @@ enum ONCHAIN_CONFIG_KEY {
// https://t.me/c/1599543687/73009
TOKEN_GHIBLICZ = "TOKEN_GHIBLICZ",
// https://t.me/c/1599543687/73347
TOKEN_ETH = "TOKEN_ETH",
}

View File

@@ -350,4 +350,14 @@ export const stxTokenContractAddresses_legacy: Record<
contractName: "bsc-ghiblicz",
}),
},
[KnownTokenId.Stacks.ETH]: {
[KnownChainId.Stacks.Mainnet]: wrapContractAddress("mainnet", {
deployerAddress: xlinkContractsMultisigMainnet,
contractName: "token-eth",
}),
[KnownChainId.Stacks.Testnet]: wrapContractAddress("testnet", {
deployerAddress: xlinkContractsMultisigTestnet,
contractName: "token-eth",
}),
},
}

View File

@@ -84,6 +84,7 @@ export namespace KnownTokenId {
export const STX = tokenId("evm-stx")
export const TRUMP = tokenId("evm-trump")
export const GHIBLICZ = tokenId("evm-ghiblicz")
export const ETH = tokenId("evm-eth")
}
/** This type includes all known tokens on EVM-compatible blockchains. */
export type EVMToken = (typeof _allKnownEVMTokens)[number]
@@ -116,6 +117,7 @@ export namespace KnownTokenId {
export const STX = tokenId("stx-stx")
export const TRUMP = tokenId("stx-trump")
export const GHIBLICZ = tokenId("stx-ghiblicz")
export const ETH = tokenId("stx-eth")
}
const _allKnownStacksTokens = [
Stacks.sUSDT,