说明:nxtp包含有不同模块,大部分采用ts语言编写,因为本人对ts语言并不太了解,只是大概看了看代码大致结构和主要功能(不太能完全读懂所有ts细节,可能有错误之处,敬请谅解)
路由器Connext网络中的,一个在后台的自动化的参与者,主要负责提供交易流动性和促进跨链互换。
监听用户跨链交易交换请求。
提交拍卖投标以满足用户交换请求。
监视所有链上的TransactionManager合约事件,以获取TransactionPrepared事件,其中路由器匹配配置的路由器的签名地址,sendingChainId匹配事件链。
在接收链上使用amount = amount - calculatedFees调用prepare,其中calculatedFees是AMM-based 互换率、固定的0.05%费用和用户支付的gas组合。
监控所有跨链的TransactionManager合约事件,以获取transactionfulfillment事件,其中路由器与配置的路由器的签署人地址匹配,receivingChainId与事件链匹配
使用从transactionfulfillment事件发出的签名在发送链上调用fulfillment。
上图清晰的反应了:Router功能模块,以及和其相互关联的各个组件
路由主要功能主要是围绕下面代码展开:
export const makeRouter = async () => {
const requestContext = createRequestContext("makeRouter");
const methodContext = createMethodContext(makeRouter.name);
try {
// set up external, config based services
const chainData = await getChainData();
if (!chainData) {
throw new Error("Could not get chain data");
}
context.chainData = chainData;
context.config = await getConfig();
context.wallet = context.config.mnemonic
? Wallet.fromMnemonic(context.config.mnemonic)
: new Web3Signer(context.config.web3SignerUrl!);
context.signerAddress = await context.wallet.getAddress();
context.isRouterContract = context.config.routerContractAddress ? true : false;
context.routerAddress = context.config.routerContractAddress || context.signerAddress;
context.messaging = await initMessaging({
signer: context.wallet,
authUrl: context.config.authUrl,
natsUrl: context.config.natsUrl,
logger: context.logger,
});
// TODO: txserviceconfig log level
context.txService = new TransactionService(
context.logger.child({ module: "TransactionService" }, context.config.logLevel),
context.config.chainConfig as any,
context.wallet,
);
// 创建cache,主要是存储bid订单信息,内部有增加、删除、确认bid等功能函数
context.cache = createRouterCache();
// adapters
//通过subgraph,获取链上数据
context.contractReader = subgraphContractReader();
//直接通过中继获取链上(合约TransactionManager)事件信息
context.contractWriter = contractWriter();
context.chainAssetSwapPoolMap = await getSwapPoolMap({
txService: context.txService,
isRouterContract: context.isRouterContract,
swapPools: context.config.swapPools,
routerAddress: context.routerAddress,
});
// bindings
if (!context.config.diagnosticMode) {
//代码里获取getActiveTransactions交易
await bindContractReader();
} else {
logger.warn("Running router in diagnostic mode");
}
if (!context.config.cleanUpMode) {
//订阅从messaging几类消息,拍卖,状态信息,metatx请求获取订阅消息
await bindMessaging();
} else {
logger.warn("Running router in cleanup mode");
}
if (context.config.priceCacheMode) {
//从链上获取资产价格存储在cachedPriceMap(根据chainid和assetId组合作为key去存储)
await bindPrices();
} else {
logger.warn("Running router not in price cache mode");
}
//
await bindFastify();
await bindMetrics();
logger.info("Router ready!");
} catch (e) {
console.error("Error starting router :(", e);
process.exit();
}
};
subgraphContractReader() 这里读取很多函数,有些函数比较简单如获取资产余额等(getAssetBalances和getExpressiveAssetBalances区别是后者表现了某类资产详细信息
如供应量、锁定量等),主要有如下函数有getActiveTransactions,getTransactionForChain.
getActiveTransactions, 根据发送链交易检查接受链上交易看相互是否匹配,不同情况,需做不同处理,看起来是做了不同的状态标示便于后续处理
getTransactionForChain,在指定链上检索具有给定transactionId-user组合的交易(交易状态、中继费用、投标情况等信息)。
contractWriter() 监听TransactionManager合约三个事件,TransactionPrepared,TransactionCancelled,LiquidityRemoved(后续ts事件处理操作没太看明白)
bindContractReader()->getActiveTransactions()->handleActiveTransactions() 依次调用
handleActiveTransactions(transactions); 根据各交易状态继续处理,经过一系列校验,然后两类交易ReceiverFulfilled会继续fufill,,SenderPrepared会继续prepare,最后通过txservice发送交易到链上,其余状态会执行cancel取消交易,各种状态如下:
bindFastify()内部有一系列处理流动性功能相关服务,可增加、删除、移动路由器资产流动性等功能,还有处理active交易(内部调用了contractReader.getActiveTransactions()->handleActiveTransactions(activeTxs))
很高兴能和你交流技术、人生等各种话题:
twitter:https://twitter.com/tylz_cai