diff --git a/apollo/src/xtoken/transfer.service.ts b/apollo/src/xtoken/transfer.service.ts index 7b13882a..c9d8dd71 100644 --- a/apollo/src/xtoken/transfer.service.ts +++ b/apollo/src/xtoken/transfer.service.ts @@ -7,7 +7,8 @@ import { AddressTokenMap } from '../base/AddressToken'; export class TransferService extends BaseTransferServiceT2 { private readonly darwainiaUrl = this.configService.get('XTOKEN_DARWINIA'); private readonly ethereumUrl = this.configService.get('XTOKEN_ETHEREUM'); - private readonly dispatchSubgraph = this.configService.get('XTOKEN_DISPATCH'); + private readonly darwiniaDispatchSubgraph = this.configService.get('XTOKEN_DISPATCH_DARWINIA'); + private readonly ethereumDispatchSubgraph = this.configService.get('XTOKEN_DISPATCH_ETHEREUM'); formalChainTransfers: PartnerT2[] = []; @@ -45,10 +46,10 @@ export class TransferService extends BaseTransferServiceT2 { ]; dispatchEndPoints = { - 'crab-dvm': this.dispatchSubgraph + '/crab', - sepolia: this.dispatchSubgraph + '/sepolia', - darwinia: this.dispatchSubgraph + '/darwinia', - ethereum: this.dispatchSubgraph + '/ethereum', + 'crab-dvm': this.darwiniaDispatchSubgraph, + sepolia: this.ethereumDispatchSubgraph, + darwinia: this.darwiniaDispatchSubgraph, + ethereum: this.ethereumDispatchSubgraph, }; addressToTokenInfo: { [key: string]: AddressTokenMap } = {}; diff --git a/apollo/src/xtoken/xtoken.service.ts b/apollo/src/xtoken/xtoken.service.ts index c657de1b..60667584 100644 --- a/apollo/src/xtoken/xtoken.service.ts +++ b/apollo/src/xtoken/xtoken.service.ts @@ -106,7 +106,7 @@ export class xTokenService implements OnModuleInit { latestNonce = firstRecord ? Number(firstRecord.nonce) : 0; } - const query = `query { transferRecords(first: ${this.baseConfigure.fetchHistoryDataFirst}, orderBy: nonce, orderDirection: asc, skip: ${latestNonce}) { id, direction, remoteChainId, nonce, sender, receiver, token, amount, timestamp, transactionHash, fee } }`; + const query = `query { transferRecords(first: ${this.baseConfigure.fetchHistoryDataFirst}, orderBy: nonce, orderDirection: asc, skip: ${latestNonce}) { id, direction, remoteChainId, nonce, messageId, sender, receiver, token, amount, timestamp, transactionHash, fee } }`; const records = await axios .post(transfer.url, { @@ -143,7 +143,7 @@ export class xTokenService implements OnModuleInit { fromChain: transfer.chain, toChain: toChain.chain, bridge: 'xtoken-' + transfer.chain, - messageNonce: record.nonce, + messageNonce: record.messageId, nonce: latestNonce + 1, requestTxHash: record.transactionHash, sender: record.sender, @@ -197,14 +197,15 @@ export class xTokenService implements OnModuleInit { } for (const uncheckedRecord of uncheckedRecords) { - const id = this.nodeIdToTransferId(uncheckedRecord.id); + const sourceId = this.nodeIdToTransferId(uncheckedRecord.id); + const messageId = uncheckedRecord.messageNonce; const node = await axios .post(this.transferService.dispatchEndPoints[uncheckedRecord.toChain], { - query: `query { messageDispatchedResult (id: \"${id}\") { id, token, transactionHash, result, timestamp }}`, + query: `query { messageDispatchedResult (id: \"${messageId}\") { id, token, transactionHash, result, timestamp }}`, variables: null, }) .then((res) => res.data?.data?.messageDispatchedResult); - if (node === undefined || node.result === null) { + if (node === undefined || node === null || node.result === null) { continue; } let result = uncheckedRecord.result; @@ -229,7 +230,7 @@ export class xTokenService implements OnModuleInit { if (uncheckedRecord.result === RecordStatus.pending || uncheckedRecord.result === RecordStatus.pendingToClaim) { if (result !== uncheckedRecord.result) { this.logger.log( - `${this.baseConfigure.name} [${uncheckedRecord.fromChain}-${uncheckedRecord.toChain}] status updated, id: ${id}, status ${uncheckedRecord.result}->${result}` + `${this.baseConfigure.name} [${uncheckedRecord.fromChain}-${uncheckedRecord.toChain}] status updated, id: ${sourceId}, status ${uncheckedRecord.result}->${result}` ); await this.aggregationService.updateHistoryRecord({ where: { id: uncheckedRecord.id }, @@ -255,7 +256,7 @@ export class xTokenService implements OnModuleInit { // all refund requests const nodes = await axios .post(destChain.url, { - query: `query { refundTransferRecords (where: {sourceId: "${id}"}) { id, sourceId, transactionHash, timestamp }}`, + query: `query { refundTransferRecords (where: {sourceId: "${sourceId}"}) { id, sourceId, transactionHash, timestamp }}`, variables: null, }) .then((res) => res.data?.data?.refundTransferRecords); diff --git a/subgraph/xtoken/messageDispatcher/abis/Guard.json b/subgraph/xtoken/messageDispatcher/abis/Guard.json index f0393e3b..e3ce93ab 100644 --- a/subgraph/xtoken/messageDispatcher/abis/Guard.json +++ b/subgraph/xtoken/messageDispatcher/abis/Guard.json @@ -15,11 +15,6 @@ "internalType": "uint256", "name": "_maxUnclaimableTime", "type": "uint256" - }, - { - "internalType": "address", - "name": "_depositor", - "type": "address" } ], "stateMutability": "nonpayable", @@ -93,12 +88,24 @@ { "anonymous": false, "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + }, { "indexed": false, "internalType": "uint256", "name": "id", "type": "uint256" }, + { + "indexed": false, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, { "indexed": false, "internalType": "address", @@ -218,6 +225,11 @@ }, { "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, { "internalType": "uint256", "name": "id", @@ -256,6 +268,11 @@ }, { "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, { "internalType": "uint256", "name": "id", @@ -280,6 +297,11 @@ "internalType": "uint256", "name": "amount", "type": "uint256" + }, + { + "internalType": "bool", + "name": "isNative", + "type": "bool" } ], "name": "claimByTimeout", @@ -289,11 +311,21 @@ }, { "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, { "internalType": "uint256", "name": "id", "type": "uint256" }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, { "internalType": "address", "name": "token", @@ -308,24 +340,44 @@ "internalType": "uint256", "name": "amount", "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "signatures", + "type": "bytes[]" } ], - "name": "deposit", + "name": "claimNative", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "depositor", - "outputs": [ + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, { "internalType": "address", - "name": "", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "stateMutability": "view", + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { @@ -524,6 +576,37 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "depositor", + "type": "address" + }, + { + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "setDepositor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxUnclaimableTime", + "type": "uint256" + } + ], + "name": "setMaxUnclaimableTime", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { diff --git a/subgraph/xtoken/messageDispatcher/abis/MsglineMessager.json b/subgraph/xtoken/messageDispatcher/abis/MsglineMessager.json index 069da754..e56a7398 100644 --- a/subgraph/xtoken/messageDispatcher/abis/MsglineMessager.json +++ b/subgraph/xtoken/messageDispatcher/abis/MsglineMessager.json @@ -24,12 +24,6 @@ "name": "srcAppChainId", "type": "uint256" }, - { - "indexed": false, - "internalType": "bytes32", - "name": "transferId", - "type": "bytes32" - }, { "indexed": false, "internalType": "bool", @@ -49,12 +43,6 @@ "name": "srcAppChainId", "type": "uint256" }, - { - "indexed": false, - "internalType": "bytes32", - "name": "transferId", - "type": "bytes32" - }, { "indexed": false, "internalType": "address", @@ -85,51 +73,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "latestRecvMessageId", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestSentMessageId", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "messageId", - "type": "bytes32" - } - ], - "name": "messageDelivered", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { diff --git a/subgraph/xtoken/messageDispatcher/generate.sh b/subgraph/xtoken/messageDispatcher/generate.sh index 8c1567eb..4894721d 100644 --- a/subgraph/xtoken/messageDispatcher/generate.sh +++ b/subgraph/xtoken/messageDispatcher/generate.sh @@ -40,8 +40,9 @@ dataSources: - name: MsglineMessager file: ./abis/MsglineMessager.json eventHandlers: - - event: CallResult(uint256,bytes32,bool) + - event: CallResult(uint256,bool) handler: handleCallResult + receipt: true file: ./src/dispatch.ts" > subgraph.yaml } @@ -64,7 +65,7 @@ echo " - kind: ethereum/contract - name: Guard file: ./abis/Guard.json eventHandlers: - - event: TokenDeposit(uint256,address,address,uint256) + - event: TokenDeposit(address,uint256,uint256,address,address,uint256) handler: handleTokenDeposit - event: TokenClaimed(uint256) handler: handleTokenClaimed diff --git a/subgraph/xtoken/messageDispatcher/package.json b/subgraph/xtoken/messageDispatcher/package.json index 2a53a91d..bdd42568 100644 --- a/subgraph/xtoken/messageDispatcher/package.json +++ b/subgraph/xtoken/messageDispatcher/package.json @@ -4,8 +4,8 @@ "scripts": { "codegen": "graph codegen", "build": "graph build", - "build-crab": "sh generate.sh dispatch crab 1877745 0x000000000EFcBAdA3793cC59c62D79b9f56Ae48F 0xCAb1f69C671f1548fd3dE5d63852E9B9181a0D0E && graph codegen && graph build", - "build-sepolia": "sh generate.sh dispatch sepolia 4865695 0x000000000EFcBAdA3793cC59c62D79b9f56Ae48F 0x527B67a61C6E1344C359Af2e241aAFeb0c3a9DE9 && sh generate.sh guard sepolia 0x2e8B5408Ec891AbdeE9CDeDCe407217c5e47196d 4865695 && graph codegen && graph build", + "build-crab": "sh generate.sh dispatch crab 1962560 0x0000000000D2de3e2444926c4577b0A59F1DD8BC 0xf85638B61E0425D6BB91981190B73246e3AF3CA9 && graph codegen && graph build", + "build-sepolia": "sh generate.sh dispatch sepolia 4952560 0x0000000000D2de3e2444926c4577b0A59F1DD8BC 0xc876D0873e4060472334E297b2db200Ca10cc806 && sh generate.sh guard sepolia 0x2e8B5408Ec891AbdeE9CDeDCe407217c5e47196d 4952560 && graph codegen && graph build", "create-remote-dev": "graph create --access-token ${KEY} --node https://thegraph-g2.darwinia.network/helix/deploy/ xtokendispatch/${NETWORK}", "deploy-remote-dev": "graph deploy --access-token $KEY --node https://thegraph-g2.darwinia.network/helix/deploy/ --ipfs https://ipfs.network.thegraph.com xtokendispatch/$NETWORK", "create-remote-pro": "graph create --access-token ${KEY} --node https://thegraph.darwinia.network/helix/deploy/ xtokendispatch/${NETWORK}", diff --git a/subgraph/xtoken/messageDispatcher/src/dispatch.ts b/subgraph/xtoken/messageDispatcher/src/dispatch.ts index ab29b190..2c8d710a 100644 --- a/subgraph/xtoken/messageDispatcher/src/dispatch.ts +++ b/subgraph/xtoken/messageDispatcher/src/dispatch.ts @@ -1,4 +1,4 @@ -import { BigInt } from "@graphprotocol/graph-ts" +import { BigInt, ethereum } from "@graphprotocol/graph-ts" import { MessageDispatched, } from "../generated/ormp/ormp" @@ -16,6 +16,16 @@ const STATUS_FAILED = 1; // 2. need to claim: pending to claim const STATUS_DELIVERED_SUCCESSED = 2; +function isMsglineContract(event: ethereum.Log): boolean { + return event.address.toHexString() == '0x00000000001523057a05d6293c1e5171ee33ee0a' || + event.address.toHexString() == '0x00000000046bc530804d66b6b64f7af69b4e4e81'; +} + +function isMsglineDispatchEvent(event: ethereum.Log): boolean { + return event.topics[0].toHexString() == '0x62b1dc20fd6f1518626da5b6f9897e8cd4ebadbad071bb66dc96a37c970087a8' && + isMsglineContract(event); +} + export function handleMessageDispatched(event: MessageDispatched): void { let message_id = event.params.msgHash.toHexString(); let entity = MessageDispatchedResult.load(message_id); @@ -31,10 +41,27 @@ export function handleMessageDispatched(event: MessageDispatched): void { } export function handleCallResult(event: CallResult): void { - let message_id = event.params.transferId.toHexString(); - let entity = MessageDispatchedResult.load(message_id); + var messageId = ''; + // find the messageId + if (event.receipt == null) { + return; + } else { + const logs = event.receipt!.logs; + for (var idx = 0; idx < logs.length; idx++) { + if (isMsglineDispatchEvent(logs[idx])) { + messageId = logs[idx].topics[1].toHexString(); + break; + } + } + } + + if (messageId === '') { + return; + } + + let entity = MessageDispatchedResult.load(messageId); if (entity == null) { - entity = new MessageDispatchedResult(message_id); + entity = new MessageDispatchedResult(messageId); } entity.timestamp = event.block.timestamp; entity.transactionHash = event.transaction.hash; diff --git a/subgraph/xtoken/transfer/abis/xTokenBacking.json b/subgraph/xtoken/transfer/abis/xTokenBacking.json index 7da450d7..37272756 100644 --- a/subgraph/xtoken/transfer/abis/xTokenBacking.json +++ b/subgraph/xtoken/transfer/abis/xTokenBacking.json @@ -47,12 +47,6 @@ { "anonymous": false, "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "refundId", - "type": "bytes32" - }, { "indexed": false, "internalType": "bytes32", @@ -62,7 +56,7 @@ { "indexed": false, "internalType": "address", - "name": "mappingToken", + "name": "xToken", "type": "address" }, { @@ -96,6 +90,12 @@ "name": "transferId", "type": "bytes32" }, + { + "indexed": false, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, { "indexed": false, "internalType": "uint256", @@ -249,6 +249,45 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "TRANSFER_DELIVERED", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_REFUNDED", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_UNFILLED", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -333,6 +372,11 @@ "name": "_originalToken", "type": "address" }, + { + "internalType": "address", + "name": "_originalSender", + "type": "address" + }, { "internalType": "address", "name": "_recipient", @@ -342,6 +386,11 @@ "internalType": "uint256", "name": "_amount", "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" } ], "name": "encodeIssuexToken", @@ -357,11 +406,6 @@ }, { "inputs": [ - { - "internalType": "bytes32", - "name": "_transferId", - "type": "bytes32" - }, { "internalType": "address", "name": "_originalToken", @@ -372,10 +416,20 @@ "name": "_originalSender", "type": "address" }, + { + "internalType": "address", + "name": "_recipient", + "type": "address" + }, { "internalType": "uint256", "name": "_amount", "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" } ], "name": "encodeIssuingForUnlockFailureFromRemote", @@ -389,6 +443,69 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "filledTransfers", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_targetChainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_originalToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_originalSender", + "type": "address" + }, + { + "internalType": "address", + "name": "_recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "getTransferId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, { "inputs": [], "name": "guard", @@ -410,24 +527,29 @@ "type": "uint256" }, { - "internalType": "bytes32", - "name": "_transferId", - "type": "bytes32" + "internalType": "address", + "name": "_originalToken", + "type": "address" }, { "internalType": "address", - "name": "_originalToken", + "name": "_originalSender", "type": "address" }, { "internalType": "address", - "name": "_originSender", + "name": "_recipient", "type": "address" }, { "internalType": "uint256", "name": "_amount", "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" } ], "name": "handleUnlockForIssuingFailureFromRemote", @@ -475,6 +597,11 @@ "name": "_amount", "type": "uint256" }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + }, { "internalType": "bytes", "name": "_extParams", @@ -486,30 +613,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "lockedMessages", - "outputs": [ - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - }, - { - "internalType": "bool", - "name": "hasRefundForFailed", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -657,9 +760,28 @@ "inputs": [ { "internalType": "bytes32", - "name": "_transferId", + "name": "", "type": "bytes32" + } + ], + "name": "requestInfos", + "outputs": [ + { + "internalType": "bool", + "name": "isRequested", + "type": "bool" }, + { + "internalType": "bool", + "name": "hasRefundForFailed", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ { "internalType": "uint256", "name": "_remoteChainId", @@ -675,11 +797,21 @@ "name": "_originalSender", "type": "address" }, + { + "internalType": "address", + "name": "_recipient", + "type": "address" + }, { "internalType": "uint256", "name": "_amount", "type": "uint256" }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + }, { "internalType": "bytes", "name": "_extParams", @@ -838,6 +970,11 @@ "name": "_originalToken", "type": "address" }, + { + "internalType": "address", + "name": "_originSender", + "type": "address" + }, { "internalType": "address", "name": "_recipient", @@ -847,6 +984,11 @@ "internalType": "uint256", "name": "_amount", "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" } ], "name": "unlockFromRemote", @@ -854,25 +996,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "unlockedTransferIds", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "unpause", diff --git a/subgraph/xtoken/transfer/abis/xTokenIssuing.json b/subgraph/xtoken/transfer/abis/xTokenIssuing.json index 0a49f980..d49e7a2b 100644 --- a/subgraph/xtoken/transfer/abis/xTokenIssuing.json +++ b/subgraph/xtoken/transfer/abis/xTokenIssuing.json @@ -8,6 +8,12 @@ "name": "transferId", "type": "bytes32" }, + { + "indexed": false, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, { "indexed": false, "internalType": "uint256", @@ -32,12 +38,6 @@ "name": "originalToken", "type": "address" }, - { - "indexed": false, - "internalType": "address", - "name": "xToken", - "type": "address" - }, { "indexed": false, "internalType": "uint256", @@ -158,12 +158,6 @@ { "anonymous": false, "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "refundId", - "type": "bytes32" - }, { "indexed": false, "internalType": "bytes32", @@ -323,6 +317,45 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "TRANSFER_DELIVERED", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_REFUNDED", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_UNFILLED", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -349,6 +382,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "_xToken", + "type": "address" + } + ], + "name": "acceptxTokenOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -366,6 +412,11 @@ "name": "_amount", "type": "uint256" }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + }, { "internalType": "bytes", "name": "_extParams", @@ -377,30 +428,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "burnMessages", - "outputs": [ - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - }, - { - "internalType": "bool", - "name": "hasRefundForFailed", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -454,11 +481,6 @@ }, { "inputs": [ - { - "internalType": "bytes32", - "name": "_transferId", - "type": "bytes32" - }, { "internalType": "address", "name": "_originalToken", @@ -469,10 +491,20 @@ "name": "_originalSender", "type": "address" }, + { + "internalType": "address", + "name": "_recipient", + "type": "address" + }, { "internalType": "uint256", "name": "_amount", "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" } ], "name": "encodeUnlockForIssuingFailureFromRemote", @@ -493,6 +525,11 @@ "name": "_originalToken", "type": "address" }, + { + "internalType": "address", + "name": "_originalSender", + "type": "address" + }, { "internalType": "address", "name": "_recipient", @@ -502,6 +539,11 @@ "internalType": "uint256", "name": "_amount", "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" } ], "name": "encodeUnlockFromRemote", @@ -515,6 +557,69 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "filledTransfers", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_targetChainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_originalToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_originalSender", + "type": "address" + }, + { + "internalType": "address", + "name": "_recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "getTransferId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, { "inputs": [], "name": "guard", @@ -535,11 +640,6 @@ "name": "_originalChainId", "type": "uint256" }, - { - "internalType": "bytes32", - "name": "_transferId", - "type": "bytes32" - }, { "internalType": "address", "name": "_originalToken", @@ -550,10 +650,20 @@ "name": "_originalSender", "type": "address" }, + { + "internalType": "address", + "name": "_recipient", + "type": "address" + }, { "internalType": "uint256", "name": "_amount", "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" } ], "name": "handleIssuingForUnlockFailureFromRemote", @@ -579,25 +689,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "issueTransferIds", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -610,6 +701,11 @@ "name": "_originalToken", "type": "address" }, + { + "internalType": "address", + "name": "_originalSender", + "type": "address" + }, { "internalType": "address", "name": "_recipient", @@ -619,6 +715,11 @@ "internalType": "uint256", "name": "_amount", "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" } ], "name": "issuexToken", @@ -799,9 +900,28 @@ "inputs": [ { "internalType": "bytes32", - "name": "_transferId", + "name": "", "type": "bytes32" + } + ], + "name": "requestInfos", + "outputs": [ + { + "internalType": "bool", + "name": "isRequested", + "type": "bool" }, + { + "internalType": "bool", + "name": "hasRefundForFailed", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ { "internalType": "uint256", "name": "_originalChainId", @@ -817,11 +937,21 @@ "name": "_originalSender", "type": "address" }, + { + "internalType": "address", + "name": "_recipient", + "type": "address" + }, { "internalType": "uint256", "name": "_amount", "type": "uint256" }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + }, { "internalType": "bytes", "name": "_extParams", @@ -955,6 +1085,24 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "_xToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_newOwner", + "type": "address" + } + ], + "name": "transferxTokenOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "unpause", diff --git a/subgraph/xtoken/transfer/generate.sh b/subgraph/xtoken/transfer/generate.sh index ce262ce1..0638942f 100644 --- a/subgraph/xtoken/transfer/generate.sh +++ b/subgraph/xtoken/transfer/generate.sh @@ -24,10 +24,12 @@ echo " - kind: ethereum/contract - name: xTokenBacking file: ./abis/xTokenBacking.json eventHandlers: - - event: TokenLocked(bytes32,uint256,address,address,address,uint256,uint256) + - event: TokenLocked(bytes32,uint256,uint256,address,address,address,uint256,uint256) handler: handleTokenLocked - - event: RemoteIssuingFailure(bytes32,bytes32,address,address,uint256,uint256) + receipt: true + - event: RemoteIssuingFailure(bytes32,address,address,uint256,uint256) handler: handleRemoteIssuingFailure + receipt: true file: ./src/xTokenBacking.ts" >> subgraph.yaml } @@ -50,10 +52,12 @@ echo " - kind: ethereum/contract - name: xTokenIssuing file: ./abis/xTokenIssuing.json eventHandlers: - - event: BurnAndRemoteUnlocked(bytes32,uint256,address,address,address,address,uint256,uint256) + - event: BurnAndRemoteUnlocked(bytes32,uint256,uint256,address,address,address,uint256,uint256) handler: handleBurnAndRemoteUnlocked - - event: RemoteUnlockForIssuingFailureRequested(bytes32,bytes32,address,address,uint256,uint256) + receipt: true + - event: RemoteUnlockForIssuingFailureRequested(bytes32,address,address,uint256,uint256) handler: handleRemoteUnlockForIssuingFailureRequested + receipt: true file: ./src/xTokenIssuing.ts" >> subgraph.yaml } diff --git a/subgraph/xtoken/transfer/package.json b/subgraph/xtoken/transfer/package.json index 6f23f5f4..6a2f3e02 100644 --- a/subgraph/xtoken/transfer/package.json +++ b/subgraph/xtoken/transfer/package.json @@ -4,8 +4,8 @@ "scripts": { "codegen": "graph codegen", "build": "graph build", - "build-crab": "sh generate.sh init && sh generate.sh backing crab 0xb137BDf1Ad5392027832f54a4409685Ef52Aa9dA 1878016 && graph codegen && graph build", - "build-sepolia": "sh generate.sh init && sh generate.sh issuing sepolia 0x44A001aF6AcD2d5f5cB82FCB14Af3d497D56faB4 4865955 && graph codegen && graph build", + "build-crab": "sh generate.sh init && sh generate.sh backing crab 0xbdC7bbF408931C5d666b4F0520E0D9E9A0B04e99 1962560 && graph codegen && graph build", + "build-sepolia": "sh generate.sh init && sh generate.sh issuing sepolia 0xf22D0bb66b39745Ae6e3fEa3E5859d7f0b367Fd1 4952560 && graph codegen && graph build", "create-remote-dev": "graph create --access-token ${KEY} --node https://thegraph-g2.darwinia.network/helix/deploy/ xtokentransfer/${NETWORK}", "deploy-remote-dev": "graph deploy --access-token $KEY --node https://thegraph-g2.darwinia.network/helix/deploy/ --ipfs https://ipfs.network.thegraph.com xtokentransfer/$NETWORK", "create-remote-pro": "graph create --access-token ${KEY} --node https://thegraph.darwinia.network/helix/deploy/ xtokentransfer/${NETWORK}", diff --git a/subgraph/xtoken/transfer/schema.graphql b/subgraph/xtoken/transfer/schema.graphql index b985bce4..3360658c 100644 --- a/subgraph/xtoken/transfer/schema.graphql +++ b/subgraph/xtoken/transfer/schema.graphql @@ -5,6 +5,7 @@ type xTokenNonceOrder @entity { type TransferRecord @entity { id: ID! + messageId: String! direction: String! remoteChainId: Int! nonce: BigInt! diff --git a/subgraph/xtoken/transfer/src/xTokenBacking.ts b/subgraph/xtoken/transfer/src/xTokenBacking.ts index 04a79cf9..ebb6e4c3 100644 --- a/subgraph/xtoken/transfer/src/xTokenBacking.ts +++ b/subgraph/xtoken/transfer/src/xTokenBacking.ts @@ -1,4 +1,4 @@ -import { BigInt, Bytes } from "@graphprotocol/graph-ts" +import { BigInt, Bytes, ethereum } from "@graphprotocol/graph-ts" import { TokenLocked, RemoteIssuingFailure, @@ -7,6 +7,21 @@ import { xTokenNonceOrder, TransferRecord, RefundTransferRecord } from "../gener const transferNonceId = "0x01"; +function isMsglineContract(event: ethereum.Log): boolean { + return event.address.toHexString() == '0x00000000001523057a05d6293c1e5171ee33ee0a' || + event.address.toHexString() == '0x00000000046bc530804d66b6b64f7af69b4e4e81'; +} + +function isMsglineAcceptEvent(event: ethereum.Log): boolean { + return event.topics[0].toHexString() == '0x327110434bca326d1f70236295f59c8b472ebc683a6549ca9254697564fec4a5' && + isMsglineContract(event); +} + +function isMsglineDeliveryEvent(event: ethereum.Log): boolean { + return event.topics[0].toHexString() == '0x62b1dc20fd6f1518626da5b6f9897e8cd4ebadbad071bb66dc96a37c970087a8' && + isMsglineContract(event); +} + export function handleTokenLocked(event: TokenLocked): void { let message_id = event.params.transferId.toHexString(); let entity = TransferRecord.load(message_id); @@ -32,15 +47,48 @@ export function handleTokenLocked(event: TokenLocked): void { entity.transactionHash = event.transaction.hash; entity.timestamp = event.block.timestamp; entity.fee = event.params.fee; + + var messageId: string; + // find the messageId + if (event.receipt == null) { + return; + } else { + const logs = event.receipt!.logs; + for (var idx = 0; idx < logs.length; idx++) { + if (isMsglineAcceptEvent(logs[idx])) { + messageId = logs[idx].topics[1].toHexString(); + break; + } + } + } + if (!messageId) { + return; + } + entity.messageId = messageId; entity.save(); } // refund txs export function handleRemoteIssuingFailure(event: RemoteIssuingFailure): void { - let id = event.params.refundId.toHexString(); - let entity = RefundTransferRecord.load(id); + var messageId = ''; + if (event.receipt == null) { + return; + } else { + const logs = event.receipt!.logs; + for (var idx = 0; idx < logs.length; idx++) { + if (isMsglineAcceptEvent(logs[idx])) { + messageId = logs[idx].topics[1].toHexString(); + break; + } + } + } + if (!messageId) { + return; + } + + let entity = RefundTransferRecord.load(messageId); if (entity == null) { - entity = new RefundTransferRecord(id); + entity = new RefundTransferRecord(messageId); } entity.sourceId = event.params.transferId.toHexString(); entity.timestamp = event.block.timestamp; diff --git a/subgraph/xtoken/transfer/src/xTokenIssuing.ts b/subgraph/xtoken/transfer/src/xTokenIssuing.ts index 0f99e418..c2e23dd2 100644 --- a/subgraph/xtoken/transfer/src/xTokenIssuing.ts +++ b/subgraph/xtoken/transfer/src/xTokenIssuing.ts @@ -1,4 +1,4 @@ -import { BigInt, Bytes } from "@graphprotocol/graph-ts" +import { BigInt, Bytes, ethereum } from "@graphprotocol/graph-ts" import { BurnAndRemoteUnlocked, RemoteUnlockForIssuingFailureRequested, @@ -7,6 +7,21 @@ import { xTokenNonceOrder, TransferRecord, RefundTransferRecord } from "../gener const transferNonceId = "0x01"; +function isMsglineContract(event: ethereum.Log): boolean { + return event.address.toHexString() == '0x00000000001523057a05d6293c1e5171ee33ee0a' || + event.address.toHexString() == '0x00000000046bc530804d66b6b64f7af69b4e4e81'; +} + +function isMsglineAcceptEvent(event: ethereum.Log): boolean { + return event.topics[0].toHexString() == '0x327110434bca326d1f70236295f59c8b472ebc683a6549ca9254697564fec4a5' && + isMsglineContract(event); +} + +function isMsglineDeliveryEvent(event: ethereum.Log): boolean { + return event.topics[0].toHexString() == '0x62b1dc20fd6f1518626da5b6f9897e8cd4ebadbad071bb66dc96a37c970087a8' && + isMsglineContract(event); +} + export function handleBurnAndRemoteUnlocked(event: BurnAndRemoteUnlocked): void { let message_id = event.params.transferId.toHexString(); let entity = TransferRecord.load(message_id); @@ -32,15 +47,47 @@ export function handleBurnAndRemoteUnlocked(event: BurnAndRemoteUnlocked): void entity.transactionHash = event.transaction.hash; entity.timestamp = event.block.timestamp; entity.fee = event.params.fee; + + var messageId: string; + // find the messageId + if (event.receipt == null) { + return; + } else { + const logs = event.receipt!.logs; + for (var idx = 0; idx < logs.length; idx++) { + if (isMsglineAcceptEvent(logs[idx])) { + messageId = logs[idx].topics[1].toHexString(); + break; + } + } + } + if (!messageId) { + return; + } + entity.messageId = messageId; entity.save(); } // refund txs export function handleRemoteUnlockForIssuingFailureRequested(event: RemoteUnlockForIssuingFailureRequested): void { - let id = event.params.refundId.toHexString(); - let entity = RefundTransferRecord.load(id); + var messageId = ''; + if (event.receipt == null) { + return; + } else { + const logs = event.receipt!.logs; + for (var idx = 0; idx < logs.length; idx++) { + if (isMsglineAcceptEvent(logs[idx])) { + messageId = logs[idx].topics[1].toHexString(); + break; + } + } + } + if (!messageId) { + return; + } + let entity = RefundTransferRecord.load(messageId); if (entity == null) { - entity = new RefundTransferRecord(id); + entity = new RefundTransferRecord(messageId); } entity.sourceId = event.params.transferId.toHexString(); entity.timestamp = event.block.timestamp;