UNPKG

lisk-framework

Version:

Lisk blockchain application platform

152 lines 8.47 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TokenInteroperableMethod = void 0; const lisk_validator_1 = require("@liskhq/lisk-validator"); const lisk_codec_1 = require("@liskhq/lisk-codec"); const base_cc_method_1 = require("../interoperability/base_cc_method"); const constants_1 = require("./constants"); const escrow_1 = require("./stores/escrow"); const user_1 = require("./stores/user"); const before_ccc_execution_1 = require("./events/before_ccc_execution"); const recover_1 = require("./events/recover"); const constants_2 = require("../interoperability/constants"); const before_ccm_forwarding_1 = require("./events/before_ccm_forwarding"); const utils_1 = require("./utils"); const utils_2 = require("../interoperability/utils"); class TokenInteroperableMethod extends base_cc_method_1.BaseCCMethod { addDependencies(interoperabilityMethod, internalMethod) { this._interopMethod = interoperabilityMethod; this._internalMethod = internalMethod; } async beforeCrossChainCommandExecute(ctx) { const { transaction: { senderAddress: relayerAddress }, ccm, } = ctx; const methodContext = ctx.getMethodContext(); const tokenID = await this._interopMethod.getMessageFeeTokenIDFromCCM(methodContext, ccm); const { ccmID } = (0, utils_2.getEncodedCCMAndID)(ccm); const [chainID] = (0, utils_1.splitTokenID)(tokenID); const userStore = this.stores.get(user_1.UserStore); if (chainID.equals(ctx.chainID)) { const escrowStore = this.stores.get(escrow_1.EscrowStore); const escrowKey = escrowStore.getKey(ccm.sendingChainID, tokenID); const escrowAccount = await escrowStore.getOrDefault(methodContext, escrowKey); if (escrowAccount.amount < ccm.fee) { this.events.get(before_ccc_execution_1.BeforeCCCExecutionEvent).error(methodContext, { ccmID, messageFeeTokenID: tokenID, relayerAddress, }, 13); throw new Error('Insufficient balance in the sending chain for the message fee.'); } escrowAccount.amount -= ccm.fee; await escrowStore.set(methodContext, escrowKey, escrowAccount); } await userStore.addAvailableBalance(methodContext, relayerAddress, tokenID, ccm.fee); this.events.get(before_ccc_execution_1.BeforeCCCExecutionEvent).log(methodContext, { ccmID, messageFeeTokenID: tokenID, relayerAddress, }); } async beforeCrossChainMessageForwarding(ctx) { const { transaction: { senderAddress: relayerAddress }, ccm, ccmFailed, } = ctx; const { ccmID } = (0, utils_2.getEncodedCCMAndID)(ccm); const methodContext = ctx.getMethodContext(); const messageFeeTokenID = await this._interopMethod.getMessageFeeTokenIDFromCCM(methodContext, ccm); if (!messageFeeTokenID.equals((0, utils_2.getTokenIDLSK)(ctx.chainID))) { throw new Error('Message fee token should be LSK.'); } const escrowStore = this.stores.get(escrow_1.EscrowStore); if (ccm.fee > 0) { const sendingChainEscrowKey = escrowStore.getKey(ccm.sendingChainID, messageFeeTokenID); const sendingChainEscrowAccount = await escrowStore.getOrDefault(methodContext, sendingChainEscrowKey); if (sendingChainEscrowAccount.amount < ccm.fee) { this.events.get(before_ccm_forwarding_1.BeforeCCMForwardingEvent).error(methodContext, ccm.sendingChainID, ccm.receivingChainID, { ccmID, messageFeeTokenID, }, 13); throw new Error('Insufficient balance in the sending chain for the message fee.'); } sendingChainEscrowAccount.amount -= ccm.fee; await escrowStore.set(methodContext, sendingChainEscrowKey, sendingChainEscrowAccount); if (ccmFailed) { const userStore = this.stores.get(user_1.UserStore); await userStore.addAvailableBalance(methodContext, relayerAddress, messageFeeTokenID, ccm.fee); } else { const receivingChainEscrowKey = escrowStore.getKey(ccm.receivingChainID, messageFeeTokenID); const receivingChainEscrowAccount = await escrowStore.getOrDefault(methodContext, receivingChainEscrowKey); receivingChainEscrowAccount.amount += ccm.fee; await escrowStore.set(methodContext, receivingChainEscrowKey, receivingChainEscrowAccount); } } this.events .get(before_ccm_forwarding_1.BeforeCCMForwardingEvent) .log(methodContext, ccm.sendingChainID, ccm.receivingChainID, { ccmID, messageFeeTokenID, }); } async verifyCrossChainMessage(ctx) { const { ccm } = ctx; const methodContext = ctx.getMethodContext(); const tokenID = await this._interopMethod.getMessageFeeTokenIDFromCCM(methodContext, ccm); const [chainID] = (0, utils_1.splitTokenID)(tokenID); if (chainID.equals(ctx.chainID)) { const escrowStore = this.stores.get(escrow_1.EscrowStore); const escrowAccount = await escrowStore.getOrDefault(methodContext, escrowStore.getKey(ccm.sendingChainID, tokenID)); if (escrowAccount.amount < ccm.fee) { throw new Error('Insufficient escrow amount.'); } } } async recover(ctx) { const methodContext = ctx.getMethodContext(); const userStore = this.stores.get(user_1.UserStore); const address = ctx.storeKey.slice(0, constants_1.ADDRESS_LENGTH); let account; if (!ctx.substorePrefix.equals(userStore.subStorePrefix) || ctx.storeKey.length !== constants_1.ADDRESS_LENGTH + constants_1.TOKEN_ID_LENGTH) { this.events .get(recover_1.RecoverEvent) .error(methodContext, address, { terminatedChainID: ctx.terminatedChainID, tokenID: constants_2.EMPTY_BYTES, amount: BigInt(0) }, 6); throw new Error('Invalid arguments.'); } try { account = lisk_codec_1.codec.decode(user_1.userStoreSchema, ctx.storeValue); lisk_validator_1.validator.validate(user_1.userStoreSchema, account); } catch (error) { this.events .get(recover_1.RecoverEvent) .error(methodContext, address, { terminatedChainID: ctx.terminatedChainID, tokenID: constants_2.EMPTY_BYTES, amount: BigInt(0) }, 6); throw new Error('Invalid arguments.'); } const chainID = ctx.storeKey.slice(constants_1.ADDRESS_LENGTH, constants_1.ADDRESS_LENGTH + constants_1.CHAIN_ID_LENGTH); const tokenID = ctx.storeKey.slice(constants_1.ADDRESS_LENGTH, constants_1.ADDRESS_LENGTH + constants_1.TOKEN_ID_LENGTH); const totalAmount = account.availableBalance + account.lockedBalances.reduce((prev, curr) => prev + curr.amount, BigInt(0)); const escrowStore = this.stores.get(escrow_1.EscrowStore); const escrowKey = escrowStore.getKey(ctx.terminatedChainID, tokenID); const escrowData = await escrowStore.getOrDefault(methodContext, escrowKey); if (!ctx.chainID.equals(chainID) || escrowData.amount < totalAmount) { this.events .get(recover_1.RecoverEvent) .error(methodContext, address, { terminatedChainID: ctx.terminatedChainID, tokenID, amount: totalAmount }, 7); throw new Error('Insufficient escrow amount.'); } escrowData.amount -= totalAmount; await escrowStore.set(methodContext, escrowKey, escrowData); const userExists = await userStore.has(methodContext, userStore.getKey(address, tokenID)); if (!userExists) { await this._internalMethod.initializeUserAccount(methodContext, address, tokenID); } await userStore.addAvailableBalance(methodContext, address, tokenID, totalAmount); this.events.get(recover_1.RecoverEvent).log(methodContext, address, { terminatedChainID: ctx.terminatedChainID, tokenID, amount: totalAmount, }); } } exports.TokenInteroperableMethod = TokenInteroperableMethod; //# sourceMappingURL=cc_method.js.map