lisk-framework
Version:
Lisk blockchain application platform
152 lines • 8.47 kB
JavaScript
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
;