개요
TED Protocol 통합 방식:| 방식 | 복잡도 | 상태 |
|---|---|---|
| 직접 컨트랙트 호출 | 중간 | 사용 가능 |
| SDK | 낮음 | 출시 예정 |
| 임베디드 위젯 | 최저 | 출시 예정 |
사전 요구사항
- Web3 라이브러리 (ethers.js, web3.js 또는 viem)
- 컨트랙트 주소의 TED Protocol 주소
- 컨트랙트 ABI
설정
TED Protocol 연결 초기화:복사
import { ethers } from 'ethers';
// 컨트랙트 주소 (예시 - contract-addresses 페이지에서 확인)
const DIAMOND_ADDRESS = "0x..."; // 네트워크별
// 통합 ABI (모든 facet 포함)
const TED_ABI = [
// IFXSwap
"function swap(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, uint256 deadline) returns (uint256)",
"function getQuote(address tokenIn, address tokenOut, uint256 amountIn) view returns (tuple(uint256 amountOut, uint256 priceImpact, address[] route, uint256 gasEstimate))",
// ICrossChainSwap
"function crossChainSwap(tuple(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, uint32 srcChainId, uint32 dstChainId, address recipient, uint256 deadline, bytes bridgeOptions)) payable returns (bytes32)",
"function estimateFees(tuple(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, uint32 srcChainId, uint32 dstChainId, address recipient, uint256 deadline, bytes bridgeOptions)) view returns (uint256, uint256)",
// Events
"event Swap(address indexed sender, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut, address dex)",
"event CrossChainSwapInitiated(bytes32 indexed messageId, address indexed sender, uint32 srcChainId, uint32 dstChainId, address tokenIn, address tokenOut, uint256 amountIn)"
];
// 초기화
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const tedProtocol = new ethers.Contract(DIAMOND_ADDRESS, TED_ABI, signer);
동일 체인 스왑
단일 체인에서 스왑 실행:- 토큰 승인
- 견적 조회
- 슬리피지 적용 최소 출력 계산
- 스왑 실행
복사
async function executeSwap(tokenIn, tokenOut, amountIn, slippageBps = 50) {
// 1. 토큰 승인 (아직 승인되지 않은 경우)
const tokenContract = new ethers.Contract(tokenIn, ERC20_ABI, signer);
const allowance = await tokenContract.allowance(userAddress, DIAMOND_ADDRESS);
if (allowance < amountIn) {
const approveTx = await tokenContract.approve(DIAMOND_ADDRESS, amountIn);
await approveTx.wait();
}
// 2. 견적 조회
const quote = await tedProtocol.getQuote(tokenIn, tokenOut, amountIn);
// 3. 슬리피지 적용 최소 출력 계산
const minAmountOut = quote.amountOut * (10000n - BigInt(slippageBps)) / 10000n;
// 4. 스왑 실행
const deadline = Math.floor(Date.now() / 1000) + 600; // 10분
const tx = await tedProtocol.swap(
tokenIn,
tokenOut,
amountIn,
minAmountOut,
deadline
);
const receipt = await tx.wait();
// 5. 확인을 위한 이벤트 파싱
const swapEvent = receipt.logs.find(log => {
try {
return tedProtocol.interface.parseLog(log)?.name === 'Swap';
} catch { return false; }
});
if (swapEvent) {
const parsed = tedProtocol.interface.parseLog(swapEvent);
return {
amountIn: parsed.args.amountIn,
amountOut: parsed.args.amountOut,
txHash: receipt.hash
};
}
}
크로스체인 스왑
서로 다른 블록체인 간 스왑 실행:복사
async function executeCrossChainSwap(params) {
const {
tokenIn,
tokenOut,
amountIn,
srcChainId,
dstChainId,
recipient,
slippageBps = 100
} = params;
// 1. 토큰 승인
const tokenContract = new ethers.Contract(tokenIn, ERC20_ABI, signer);
const approveTx = await tokenContract.approve(DIAMOND_ADDRESS, amountIn);
await approveTx.wait();
// 2. 수수료 추정
const crossChainParams = {
tokenIn,
tokenOut,
amountIn,
minAmountOut: 0n, // 견적 후 계산
srcChainId,
dstChainId,
recipient,
deadline: Math.floor(Date.now() / 1000) + 3600,
bridgeOptions: "0x"
};
const [nativeFee, bridgeFee] = await tedProtocol.estimateFees(crossChainParams);
// 3. 예상 출력 조회 및 최소값 설정
const quote = await tedProtocol.getQuote(tokenIn, tokenOut, amountIn);
crossChainParams.minAmountOut = quote.amountOut * (10000n - BigInt(slippageBps)) / 10000n;
// 4. 크로스체인 스왑 실행
const tx = await tedProtocol.crossChainSwap(crossChainParams, {
value: nativeFee
});
const receipt = await tx.wait();
// 5. 추적을 위한 메시지 ID 조회
const event = receipt.logs.find(log => {
try {
return tedProtocol.interface.parseLog(log)?.name === 'CrossChainSwapInitiated';
} catch { return false; }
});
if (event) {
const parsed = tedProtocol.interface.parseLog(event);
return {
messageId: parsed.args.messageId,
txHash: receipt.hash
};
}
}
크로스체인 전송 추적
LayerZero Scan API로 전송 상태 모니터링:복사
async function trackTransfer(messageId) {
const response = await fetch(
`https://api.layerzeroscan.com/tx/${messageId}`
);
const data = await response.json();
return {
status: data.status, // 'INFLIGHT', 'DELIVERED', 'FAILED'
srcTxHash: data.srcTxHash,
dstTxHash: data.dstTxHash
};
}
토큰 승인
표준 승인
프로토콜에 토큰 사용 권한 부여:복사
async function approveToken(tokenAddress, amount) {
const token = new ethers.Contract(tokenAddress, ERC20_ABI, signer);
const tx = await token.approve(DIAMOND_ADDRESS, amount);
await tx.wait();
}
Permit (가스리스 승인)
TEDP와 일부 스테이블코인에서 ERC-2612를 통해 지원됩니다.- 오프체인에서 승인 서명
- 스왑 트랜잭션에 포함
- 별도 승인 트랜잭션의 가스 절약
에러 처리
트랜잭션 실행 전 시뮬레이션 및 커스텀 에러 처리:복사
async function safeSwap(tokenIn, tokenOut, amountIn) {
try {
// 먼저 시뮬레이션
await tedProtocol.swap.staticCall(
tokenIn,
tokenOut,
amountIn,
0n, // 문제가 있으면 실패
Math.floor(Date.now() / 1000) + 600
);
// 시뮬레이션 통과하면 실행
return await executeSwap(tokenIn, tokenOut, amountIn);
} catch (error) {
// 커스텀 에러 파싱
if (error.data) {
const iface = new ethers.Interface([
"error InsufficientOutput(uint256 expected, uint256 actual)",
"error DeadlineExpired(uint256 deadline, uint256 timestamp)",
"error UnsupportedToken(address token)",
"error ProtocolPaused()"
]);
try {
const decoded = iface.parseError(error.data);
console.error(`Error: ${decoded.name}`, decoded.args);
} catch {
console.error("Unknown error:", error);
}
}
throw error;
}
}
모범 사례
최신 견적 사용
견적은 짧은 시간만 유효합니다. 견적 조회 후 즉시 실행하세요.적절한 슬리피지 설정
| 스왑 유형 | 권장 슬리피지 |
|---|---|
| 스테이블코인 쌍 | 0.1-0.5% |
| 크로스체인 스왑 | 0.5-1% |
| 대량 금액 | 더 낮게 설정 |
네트워크 전환 처리
트랜잭션 실행 전 올바른 네트워크 확인:복사
async function ensureCorrectNetwork(requiredChainId) {
const currentChainId = await provider.getNetwork().then(n => n.chainId);
if (currentChainId !== requiredChainId) {
await window.ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: ethers.toQuantity(requiredChainId) }]
});
}
}
재시도 로직 구현
네트워크 문제로 일시적 실패가 발생할 수 있습니다. 점진적으로 간격을 늘려 재시도하면 안정성이 향상됩니다.지원
- Discord — #developers 채널
- 이메일 — [email protected]
- GitHub — 이슈와 토론