稳定币服务交换提供者
目录
概览
这个 StablecoinServiceSwapProvider 通过Circle管理的Stablecoin Service,在单个区块链网络上实现令牌互换. 该供应商与DEX聚合器集成,在保持App Kits生态系统的安全性和可靠性标准的同时,寻找最佳互换路线.
虽然主要设计为电力 交换工具箱,该提供者也可以使用 直接在应用程序中 需要精细控制互换过程 或想要整合 没有完整的 App Kits 框架.
安装
npm install @circle-fin/provider-stablecoin-service-swap
# or
yarn add @circle-fin/provider-stablecoin-service-swap
说明: 默认情况下包含此提供者 交换工具箱。如果需要自定义交换集成,则直接导入此提供者.
快速启动
备选案文1:用交换套件(建议)
import { createSwapKitContext, swap, Ethereum } from '@circle-fin/swap-kit'
import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
// Create adapter
const adapter = createViemAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY,
})
// Provider included by default
const context = createSwapKitContext()
const result = await swap(context, {
from: { adapter, chain: Ethereum },
tokenIn: 'USDC',
tokenOut: 'USDT',
amountIn: '100.50',
})
备选案文2:直接提供者的使用
import { StablecoinServiceSwapProvider } from '@circle-fin/provider-stablecoin-service-swap'
import { ViemAdapter } from '@circle-fin/adapter-viem-v2'
import { Ethereum } from '@core/chains'
import { createPublicClient, createWalletClient, http } from 'viem'
import { mainnet } from 'viem/chains'
import { privateKeyToAccount } from 'viem/accounts'
const account = privateKeyToAccount(process.env.PRIVATE_KEY)
const provider = new StablecoinServiceSwapProvider()
// Create adapter
const adapter = new ViemAdapter({
publicClient: createPublicClient({ chain: mainnet, transport: http() }),
walletClient: createWalletClient({
account,
chain: mainnet,
transport: http(),
}),
})
// Check route support
const isSupported = provider.supportsRoute(
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
'0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT
Ethereum,
)
// Get swap estimate
const estimate = await provider.estimate({
from: { adapter, chain: Ethereum },
tokenInAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
tokenOutAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amountIn: '100.50',
to: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
config: { slippageBps: 300 },
})
// Execute swap
const result = await provider.swap({
from: { adapter, chain: Ethereum },
tokenInAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
tokenOutAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amountIn: '100.50',
to: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
config: { slippageBps: 300 },
})
特征
- ✅ 单链互换 - 在同一个区块链上交换代币
- ✅ 广义符号支持 - 稳定币、包裹花纹和本地花纹
- ✅ 全面审定 - 路线验证和参数检查
- ✅ 类型安全 - 包含详细错误处理的完整类型脚本支持
- ✅ 增强出错调试 - 提交后错误中的自动交易散列和探索器 URL 包含
- ✅ 许可支持 - 节能的EIP-2612许可证签字
- ✅ 定制费 - 货币化的可配置开发商费用
- ✅ 页口保护 - 停止限制执行以防止不利的互换
支持的链条
EVM 链: 基地、 以利浦、 Polygon PoS等
非EVM链页:1
说明:Testnet链不支持互换操作.
支持的托肯斯语Name
每种互换操作支持以下符号类之间的交易:
稳定币 (6 小数):
- USDC 美洲金融共同体 - 硬币
- 欧盟 - 欧币
- 乌干达 - 绳子美元
- (美元) - 支付费用
稳定币 (18 小数):
- DAI 达赖 - 制造马来币
- 美国 - Ethena美元(合成美元)
已包装的托肯斯 :
- 世界贸易中心 - 包装了比特币(8个小数)
- 韦斯 - 包装了伊特鲁姆(18个小数)
- 系统 - 包装索拉纳(9个小数)
- 瓦瓦克斯 - 包裹了雪崩(18个小数)
- 世界警察组织 - 环形多边形(18个小数)
本地托肯语 :
- 真实性 - 链状活性气体(Etheum上的ETH、索拉纳上的SOL等)
罐头可用性因链而异. 使用 supportsRoute() 用于执行互换前验证支持.
EIP-2612 无气批准
提供商自动使用 EIP- 2612 许可签名来获取支持的符号, 启用 单交易互换 不需要单独的批准交易.
如何运作
EIP-2612 支持的托肯斯 (美联储):
- 用户签署许可证( 脱链、 无气体)
- 包含许可证的交换执行
- 共计:1项交易
用于非EIP-2612 键 (美国技术合作署、美国国际开发署等):
- 执行和确认批准交易
- 交换已执行
- 共计:2起交易
提供者会自动检测到符号支持并处理适当的流量.
自动批准全部 ERC-20 键
提供者现在支持 所有 ERC-20 令牌的自动批准不仅仅是USDC。 当一个符号不支持EIP-2612许可时,提供者会明智地选择适当的批准方法:
USDC核准战略:
- 用途
increaseAllowance()函数( OpenZeppelin ERC20 扩展名) - 避免种族条件的更安全办法
- 相对增加而不是绝对值
- 环球公司就USDC提出的建议
其他ERC-20托肯斯(USDT, DAI等):
- 使用标准
approve()函数(ERC-20规格) - Uniswap, 1英寸和所有主要DEX 使用的工业标准
- 理论上的种族条件在实际中很少见
- 原子交换执行提供了额外的安全性
种族条件说明 :
标准 ERC-20 approve() 函数具有已知的理论种族条件,即恶意支出者可以先行进行批准变更。 不过:
- 这在实践上是极罕见的
- 这是公认的行业标准(所有大型DEX使用)
- 适配器合同是可信的,交换是原子的
- USDC使用更安全的
increaseAllowance()避免这一切
支助的EIP-2612 键
| 脚本 | 链条 |
|---|---|
| USDC 美洲金融共同体 | 伊特鲁姆, Base, Arbitrum, Optimism, Polygon, Avalanche, 世界连锁店, Sepolia (测试网) |
代码示例
与EIP-2612(单一交易)交换
// Swap USDC → USDT (USDC supports EIP-2612)
const result = await provider.swap({
from: { adapter, chain: Ethereum },
tokenInAddress: 'USDC', // Supports EIP-2612
tokenOutAddress: 'USDT',
amountIn: '100.00',
to: '0xRecipient',
})
// Flow: User signs permit → Swap executes (1 tx)
console.log('Completed in 1 transaction:', result.txHash)
用自动批准交换USDT( 二笔交易)
// Swap USDT → USDC (USDT doesn't support EIP-2612)
const result = await provider.swap({
from: { adapter, chain: Ethereum },
tokenInAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT
tokenOutAddress: 'USDC',
amountIn: '100.00',
to: '0xRecipient',
})
// Flow: Approval tx (uses token.approve) → Wait → Swap tx (2 txs)
console.log('Completed in 2 transactions:', result.txHash)
用自动批准交换 DAI (两笔交易)
// Swap DAI → USDC (DAI doesn't support EIP-2612 on some chains)
const result = await provider.swap({
from: { adapter, chain: Ethereum },
tokenInAddress: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI
tokenOutAddress: 'USDC',
amountIn: '1000.00',
to: '0xRecipient',
})
// Flow: Approval tx (uses token.approve) → Wait → Swap tx (2 txs)
console.log('Completed in 2 transactions:', result.txHash)
通用 ERC-20 交换
// Swap any ERC-20 token (automatic approval detection)
const result = await provider.swap({
from: { adapter, chain: Ethereum },
tokenInAddress: '0xYourTokenAddress',
tokenOutAddress: 'USDC',
amountIn: '100.00',
to: '0xRecipient',
})
// Provider automatically:
// 1. Detects if token supports EIP-2612
// 2. Uses permit (1 tx) or approve (2 tx) accordingly
// 3. Selects increaseAllowance (USDC) or approve (other tokens)
console.log('Swap completed:', result.txHash)
用户经验比较
| 假设 | 交易 | 用户动作 | 天然气成本 |
|---|---|---|---|
| EIP-2612 托肯(美国) | 1个 | 签名许可+确认互换 | 低调 |
| 非EIP-2612号 脚本 | 2个 | 确认批准 + 确认互换 | 高级 |
用法实例
基本交换操作
import { StablecoinServiceSwapProvider } from '@circle-fin/provider-stablecoin-service-swap'
import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
import { Ethereum } from '@core/chains'
// Create adapter
const adapter = createViemAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY,
})
// Instantiate provider
const provider = new StablecoinServiceSwapProvider()
// Execute swap: USDC → USDT on Ethereum
const result = await provider.swap({
from: { adapter, chain: Ethereum },
tokenInAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
tokenOutAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT
amountIn: '100.00',
to: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
config: {
slippageBps: 300, // 3% max slippage
allowanceStrategy: 'permit', // Use EIP-2612 permit
},
})
console.log('Transaction hash:', result.txHash)
console.log('Fees:', result.fees)
进行交换估计
import { StablecoinServiceSwapProvider } from '@circle-fin/provider-stablecoin-service-swap'
import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
import { Ethereum } from '@core/chains'
const adapter = createViemAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY,
})
const provider = new StablecoinServiceSwapProvider()
// Get estimate before swapping
const estimate = await provider.estimate({
from: { adapter, chain: Ethereum },
tokenInAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
tokenOutAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT
amountIn: '100.00',
to: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
config: { slippageBps: 300 },
})
console.log('Stop limit:', estimate.stopLimit) // { token: 'USDT', amount: '99.5' }
console.log('Estimated output:', estimate.estimatedOutput) // { token: 'USDT', amount: '99.5' }
console.log('Fee breakdown:', estimate.fees)
路由验证
import { StablecoinServiceSwapProvider } from '@circle-fin/provider-stablecoin-service-swap'
import { Ethereum, Base, Solana } from '@core/chains'
const provider = new StablecoinServiceSwapProvider()
// Check if USDC → USDT is supported on Ethereum
const ethereumSupported = provider.supportsRoute(
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
'0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT
Ethereum,
)
console.log('Ethereum USDC→USDT:', ethereumSupported) // true
// Check native token swap on Base
const baseNativeSupported = provider.supportsRoute(
'0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC on Base
'NATIVE', // Native gas token
Base,
)
console.log('Base USDC→NATIVE:', baseNativeSupported) // true
// Solana support
const solanaSupported = provider.supportsRoute(
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC on Solana
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB', // USDT on Solana
Solana,
)
console.log('Solana USDC→USDT:', solanaSupported) // true
自定义收费配置
供应商支持两种定制收费办法(相互排斥):
备选案文1:基于百分比(简单)
import { StablecoinServiceSwapProvider } from '@circle-fin/provider-stablecoin-service-swap'
import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
import { Ethereum } from '@core/chains'
const adapter = createViemAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY,
})
const provider = new StablecoinServiceSwapProvider()
// Percentage fee per-swap
const result = await provider.swap({
from: { adapter, chain: Ethereum },
tokenInAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
tokenOutAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT
amountIn: '100.00',
to: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
config: {
customFee: {
percentageBps: 1000, // 10% fee
recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0',
},
},
})
备选案文2:绝对数额(Via SwapKit回调)
// When using SwapKit with callback, provider receives absolute amount
const result = await provider.swap({
from: { adapter, chain: Ethereum },
tokenInAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
tokenOutAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amountIn: '100.00',
to: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
config: {
customFee: {
amount: '5000000', // 5 USDC - calculated by SwapKit callback
recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0',
},
},
})
说明: 提供商接受其中之一
percentageBps或amount(互为专有. 服务计算费用percentageBps,或使用提供的amount直接说.
配置选项
交换配置
| 选项 | 类型 | 默认 | 说明 |
|---|---|---|---|
allowanceStrategy | 'permit' | 'approve' | 'permit' | 接受批准战略 |
slippageBps | number | 300 | 基点中最大滑坡(300=3%) |
stopLimit | string | - 说吧 | 基准单位最低可接受产出 |
customFee.percentageBps | number | - 说吧 | 收费百分比(100=1%,与金额相排斥) |
customFee.amount | string | - 说吧 | 基准单位的绝对费用(与百分数相除) |
customFee.recipientAddress | string | - 说吧 | 收取费用的地址( 如果设置自定义Fee 则需要) |
apiKey | string | - 说吧 | 可选 Circle API 密钥( 持有者证书); 省略无权限模式 |
kitKey | string | - 说吧 | 折旧的别名 apiKey仍然荣耀 |
provider | string | - 说吧 | DEX 聚合符标识符 |
自定义收费 : 提供其中之一
percentageBps(服务计算) ORamount(绝对数量),不是两者兼有.
处理错误
提供者使用 KitError。错误分为两类:
- 致命错误 - 需要改变配置或用户动作的无法恢复的错误(例如无效参数、不支持的路由、余额不足)
- 可重试错误 - 重复试验时可能成功的瞬间错误(例如网络问题,暂时无法提供服务)
import { StablecoinServiceSwapProvider } from '@circle-fin/provider-stablecoin-service-swap'
import { isKitError, isFatalError, isRetryableError } from '@core/errors'
import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
import { Ethereum } from '@core/chains'
const provider = new StablecoinServiceSwapProvider()
const adapter = createViemAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY,
})
const params = {
from: { adapter, chain: Ethereum },
tokenInAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
tokenOutAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amountIn: '100.00',
to: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
}
try {
// Check route first
const isSupported = provider.supportsRoute(
params.tokenInAddress,
params.tokenOutAddress,
Ethereum,
)
if (!isSupported) {
console.error('Route not supported')
return
}
const result = await provider.swap(params)
console.log('Swap completed:', result.txHash)
} catch (error) {
if (isKitError(error)) {
console.error('Error code:', error.code)
console.error('Message:', error.message)
if (isFatalError(error)) {
// Unrecoverable error - fix configuration
console.error('Fatal error, check your parameters')
} else if (isRetryableError(error)) {
// Transient error - retry is possible
console.log('Retrying...')
}
} else {
// Unexpected error
console.error('Unexpected error:', error)
}
}
从错误中获取交易细节
当一个互换交易在提交后失败(例如返回链上,耗尽气体),错误会自动包含交易散列和块浏览器 URL以方便调试:
import { StablecoinServiceSwapProvider } from '@circle-fin/provider-stablecoin-service-swap'
import { isKitError } from '@core/errors'
import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
import { Ethereum } from '@core/chains'
const provider = new StablecoinServiceSwapProvider()
const adapter = createViemAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY,
})
try {
const result = await provider.swap({
from: { adapter, chain: Ethereum },
tokenInAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
tokenOutAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amountIn: '100.00',
to: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
})
} catch (error) {
if (isKitError(error)) {
console.error('Swap failed:', error.message)
console.error('Error code:', error.code)
// Access transaction details from error trace
const trace = error.cause?.trace as any
if (trace?.txHash) {
console.log('Transaction hash:', trace.txHash)
// Output: 0x1234567890abcdef...
}
if (trace?.explorerUrl) {
console.log('View on explorer:', trace.explorerUrl)
// Output: https://etherscan.io/tx/0x1234567890abcdef...
}
}
}
说明: 交易细节txHash 财务报告和审定财务报表 explorerUrl)仅包括发生错误时 之后 交易已提交区块链。 提交前的错误(验证、余额不足等)将不包括这些字段.
常见错误设想
| 错误 | 原因 | 决议 | 交易细节 |
|---|---|---|---|
| 不支持路线 | 链上不可用的托肯对 | 使用 supportsRoute() 在互换前进行校验 | 没有 |
| 验证失败 | 无效的参数 | 检查参数格式和类型 | 没有 |
| 余额不足 | 没有足够的符号 | 交换前验证钱包余额 | 没有 |
| 已超过 | 价格超越了容忍 | 增加 slippageBps 或重试 | 有(如果在链上) |
| 交易退回 | 链上执行失败 | 检查 explorerUrl 详细信息错误追踪 | 对 |
| 没有汽油 | 用于执行的气体不足 | 检查 explorerUrl 详细信息错误追踪 | 对 |
交换进程
提供者处理完整的互换流 :
- 验证 - 验证输入参数和路由支持
- 核准 - 赠款代金(通过许可或批准交易)
- 执行 - 向网络提交互换交易
- 确认 - 等待交易确认
每个步骤都经过跟踪,可以通过结果对象进行监测.
服务一体化架构
概览
这个 StablecoinServiceSwapProvider 集成 Circle 的 Stablecoin Service API ,以启用管理,安全的令牌互换. 集成遵循客户端-服务器架构,提供商在Circle托管的互换服务中充当客户端.
一体化流动
提供者负责以下步骤:
- 验证参数路由( R) - 确保互换请求有效
- 构建互换请求 - 构建 API 请求的有效载荷
- 调用稳定币服务 API - 让HTTPS请求为Circle服务
- 流程反应 - 验证和剖析服务响应
- 执行块链交易 - 通过适配器提交交易
API 终点
提供者与这些稳定币服务 API 端点交互 :
引用结束点
- 目的: 获得与估计数额和费用相交换的报价
- 方法数字 :
GET /v1/stablecoinKits/quote - 认证: 通过授权头的可选 API 密钥( 省略时没有允许)
- 请求: 查询带有令牌地址、 数量、 滑行的参数
- 回应: 引用估计产出、最低产出和收费内容
交换执行终点
- 目的: 执行实际的互换交易
- 方法数字 :
POST /v1/stablecoinKits/swap - 认证: 通过授权头的可选 API 密钥( 省略时没有允许)
- 请求: 交换参数,包括引用细节和地址
- 回应: 使用执行指令处理数据
认证
带有 Circle 稳定币服务的认证是可选的 。 当 API 密钥作为无记名证书发送时; 当省略时, 提供者以无权限模式运行( 否) Authorization 头曰.
证书通过下列方式提供: config.apiKey,没有在
构造器 - StablecoinServiceSwapProviderConfig 只携带 customFee。 。 。 .
const provider = new StablecoinServiceSwapProvider()
const result = await provider.swap({
from: { adapter, chain: Ethereum },
tokenInAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
tokenOutAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
amountIn: '100.00',
to: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
config: {
// Read the key from the environment; never hard-code it.
apiKey: process.env.CIRCLE_API_KEY, // <ENV>_API_KEY:<keyId>:<keySecret>
},
})
遗产
kitKey数字 :config.kitKey以有利于config.apiKey它继续工作 和遗产KIT_KEY:<keyId>:<keySecret>价值观仍然为两个字段所接受。 当两个字段都设置好时,apiKey赢了.
请求流量
交换请求
// Provider handles:
// a) Token approval (via EIP-2612 permit or approve tx)
// b) Swap execution request to service
// c) Transaction submission via adapter
// d) Confirmation waiting
// Returns:
{
txHash: '0xabc123...',
tokenInAddress: '0xA0b...',
tokenOutAddress: '0xdAC...',
amountIn: '100000000',
fees: [{ token: 'USDC', amount: '0.003' }]
}
与交换套件合并
此提供者是专门为 交换工具箱数字 :
import {
createSwapKitContext,
estimate,
swap,
getSupportedChains,
} from '@circle-fin/swap-kit'
import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
import { Ethereum } from '@circle-fin/swap-kit'
const adapter = createViemAdapterFromPrivateKey({
privateKey: process.env.PRIVATE_KEY,
})
// Provider is included by default
const context = createSwapKitContext()
// Get supported chains from all providers
const chains = getSupportedChains(context)
console.log(
'Supported chains:',
chains.map((c) => c.name),
)
// Execute swap
const result = await swap(context, {
from: { adapter, chain: Ethereum },
tokenIn: 'USDC',
tokenOut: 'USDT',
amountIn: '100.50',
config: { slippageBps: 300 },
})
console.log('Transaction:', result.txHash)
API 参考
核心方法
supportsRoute(tokenInAddress, tokenOutAddress, chain)
检查提供者是否支持互换路径 .
- 参数数字 :
tokenInAddress: string- 输入符地址或本国货币符号tokenOutAddress: string- 输出令牌地址或本国货币符号chain: ChainDefinition- 交换的链条
- 回返数字 :
boolean- 说吧true如果路径被支持
estimate(params)
在不执行交易的情况下获取交换估计 .
- 参数数字 :
ServiceSwapParams- 交换参数 - 回返数字 :
Promise<EstimateResult>- 估计数包括交易数据和收费
swap(params)
执行令牌互换操作 .
- 参数数字 :
ServiceSwapParams- 交换参数 - 回返数字 :
Promise<SwapResult>- 结果,包括交易散列和交换细节
类型
| 类型 | 说明 |
|---|---|
StablecoinServiceSwapProviderConfig | 提供者构造器配置 |
ServiceSwapParams | 互换业务参数 |
ServiceSwapConfig | 可选互换配置 |
EstimateResult | 交换估计答复 |
SwapResult | 交换执行结果 |
SwappingProvider | 交换供应商执行接口 |
AllowanceStrategy | 核准战略'permit' 或者说 'approve'(中文(简体) ) |
发展
这个包是App Kits monorepo的一部分.
# Build
nx build @circle-fin/provider-stablecoin-service-swap
# Test
nx test @circle-fin/provider-stablecoin-service-swap
# Lint
nx lint @circle-fin/provider-stablecoin-service-swap
捐款
欢迎捐款! 请看 捐款额 详细情况.
许可证
这个项目根据Apache 2.0许可证获得许可. 联系人 支助 详细情况.