Skip to content

Commit

Permalink
feat: prepare and write repay with collateral (#37)
Browse files Browse the repository at this point in the history
  • Loading branch information
palace22 authored Jun 6, 2024
1 parent d08082c commit a7babf4
Show file tree
Hide file tree
Showing 5 changed files with 212 additions and 4 deletions.
22 changes: 20 additions & 2 deletions src/chains/evm/common/utils/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,11 @@ export function buildEvmMessageData(
]);
}
case Action.RepayWithCollateral: {
throw new Error("Not implemented yet: Action.RepayWithCollateral case");
return concat([
data.loanId,
convertNumberToBytes(data.poolId, UINT8_LENGTH),
convertNumberToBytes(data.amount, UINT256_LENGTH),
]);
}
case Action.Liquidate: {
throw new Error("Not implemented yet: Action.Liquidate case");
Expand Down Expand Up @@ -417,7 +421,21 @@ export function buildEvmMessageToSend(
return message;
}
case Action.RepayWithCollateral: {
throw new Error("Not implemented yet: Action.RepayWithCollateral case");
const message: MessageToSend = {
params,
sender,
destinationChainId,
handler,
payload: buildMessagePayload(
Action.RepayWithCollateral,
accountId,
userAddress,
data,
),
finalityLevel: FINALITY.IMMEDIATE,
extraArgs,
};
return message;
}
case Action.Liquidate: {
throw new Error("Not implemented yet: Action.Liquidate case");
Expand Down
72 changes: 72 additions & 0 deletions src/chains/evm/spoke/modules/folks-evm-loan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import type {
PrepareDeleteLoanCall,
PrepareDepositCall,
PrepareRepayCall,
PrepareRepayWithCollateralCall,
PrepareWithdrawCall,
} from "../../common/types/module.js";
import type { TokenRateLimit } from "../types/pool.js";
Expand Down Expand Up @@ -296,6 +297,48 @@ export const prepare = {
token: spokeTokenData,
};
},

async repayWithCollateral(
provider: Client,
sender: EvmAddress,
messageToSend: MessageToSend,
network: NetworkType,
accountId: AccountId,
loanId: LoanId,
folksTokenId: FolksTokenId,
amount: bigint,
spokeChain: SpokeChain,
transactionOptions: EstimateGasParameters = { account: sender },
): Promise<PrepareRepayWithCollateralCall> {
const hubTokenData = getHubTokenData(folksTokenId, network);

const spokeCommonAddress = spokeChain.spokeCommonAddress;

const spokeCommon = getSpokeCommonContract(provider, spokeCommonAddress);
const bridgeRouter = getBridgeRouterSpokeContract(
provider,
spokeChain.bridgeRouterAddress,
);

// get adapter fees
const msgValue = await bridgeRouter.read.getSendFee([messageToSend]);

// get gas limits
const gasLimit = await spokeCommon.estimateGas.repayWithCollateral(
[messageToSend.params, accountId, loanId, hubTokenData.poolId, amount],
{
value: msgValue,
...transactionOptions,
},
);

return {
msgValue,
gasLimit,
messageParams: messageToSend.params,
spokeCommonAddress,
};
},
};

export const write = {
Expand Down Expand Up @@ -506,6 +549,35 @@ export const write = {
},
);
},

async repayWithCollateral(
provider: Client,
signer: WalletClient,
accountId: AccountId,
loanId: LoanId,
poolId: number,
amount: bigint,
prepareCall: PrepareRepayWithCollateralCall,
) {
const { msgValue, gasLimit, messageParams, spokeCommonAddress } =
prepareCall;

const spokeCommon = getSpokeCommonContract(
provider,
spokeCommonAddress,
signer,
);

return await spokeCommon.write.repayWithCollateral(
[messageParams, accountId, loanId, poolId, amount],
{
account: getEvmSignerAccount(signer),
chain: signer.chain,
gasLimit: gasLimit,
value: msgValue,
},
);
},
};

export const read = {
Expand Down
16 changes: 14 additions & 2 deletions src/common/types/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ export type RepayMessageData = {
maxOverRepayment: bigint;
};

export type RepayWithCollateralMessageData = {
loanId: LoanId;
poolId: number;
amount: bigint;
};

// Extra args
export type DefaultExtraArgs = "0x";

Expand All @@ -148,7 +154,6 @@ export type DefaultMessageDataParams = {
| Action.RemoveDelegate
| Action.DepositFToken
| Action.WithdrawFToken
| Action.RepayWithCollateral
| Action.Liquidate
| Action.SwitchBorrowType
| Action.SendToken;
Expand Down Expand Up @@ -212,6 +217,12 @@ export type RepayMessageDataParams = {
extraArgs: RepayExtraArgs;
};

export type RepayWithCollateralMessageDataParams = {
action: Action.RepayWithCollateral;
data: RepayWithCollateralMessageData;
extraArgs: DefaultExtraArgs;
};

export type MessageDataParams =
| DefaultMessageDataParams
| CreateAccountMessageDataParams
Expand All @@ -222,7 +233,8 @@ export type MessageDataParams =
| DepositMessageDataParams
| WithdrawMessageDataParams
| BorrowMessageDataParams
| RepayMessageDataParams;
| RepayMessageDataParams
| RepayWithCollateralMessageDataParams;

export type MessageBuilderParams = {
userAddress: GenericAddress;
Expand Down
2 changes: 2 additions & 0 deletions src/common/types/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {
PrepareCall as PrepareEVMCall,
PrepareBorrowCall as PrepareBorrowEVMCall,
PrepareRepayCall as PrepareRepayEVMCall,
PrepareRepayWithCollateralCall as PrepareRepayWithCollateralEVMCall,
} from "../../chains/evm/common/types/module.js";

export enum LoanType {
Expand All @@ -30,3 +31,4 @@ export type PrepareDepositCall = PrepareDepositEVMCall;
export type PrepareWithdrawCall = PrepareWithdrawEVMCall;
export type PrepareBorrowCall = PrepareBorrowEVMCall;
export type PrepareRepayCall = PrepareRepayEVMCall;
export type PrepareRepayWithCollateralCall = PrepareRepayWithCollateralEVMCall;
104 changes: 104 additions & 0 deletions src/xchain/modules/folks-loan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import type {
OptionalFeeParams,
RepayExtraArgs,
RepayMessageData,
RepayWithCollateralMessageData,
WithdrawMessageData,
} from "../../common/types/message.js";
import type {
Expand All @@ -56,6 +57,7 @@ import type {
PrepareCreateLoanCall,
PrepareDepositCall,
PrepareRepayCall,
PrepareRepayWithCollateralCall,
PrepareWithdrawCall,
} from "../../common/types/module.js";
import type { FolksTokenId } from "../../common/types/token.js";
Expand Down Expand Up @@ -613,6 +615,81 @@ export const prepare = {
return exhaustiveCheck(folksChain.chainType);
}
},

async repayWithCollateral(
accountId: AccountId,
loanId: LoanId,
folksTokenId: FolksTokenId,
amount: bigint,
adapters: MessageAdapters,
) {
const folksChain = FolksCore.getSelectedFolksChain();
const network = folksChain.network;

assertAdapterSupportsDataMessage(
folksChain.folksChainId,
adapters.adapterId,
);

const hubChain = getHubChain(network);
const hubTokenData = getHubTokenData(folksTokenId, network);

const spokeChain = getSpokeChain(folksChain.folksChainId, network);

const userAddress = getSignerGenericAddress({
signer: FolksCore.getFolksSigner().signer,
chainType: folksChain.chainType,
});

const data: RepayWithCollateralMessageData = {
loanId,
poolId: hubTokenData.poolId,
amount,
};
const messageBuilderParams: MessageBuilderParams = {
userAddress,
accountId,
adapters,
action: Action.RepayWithCollateral,
sender: spokeChain.spokeCommonAddress,
destinationChainId: hubChain.folksChainId,
handler: hubChain.hubAddress,
data,
extraArgs: "0x",
};
const feeParams: OptionalFeeParams = {};

feeParams.gasLimit = await estimateReceiveGasLimit(
FolksCore.getHubProvider(),
hubChain,
folksChain,
adapters,
messageBuilderParams,
);

const messageToSend = buildMessageToSend(
folksChain.chainType,
messageBuilderParams,
feeParams,
);

switch (folksChain.chainType) {
case ChainType.EVM:
return await FolksEvmLoan.prepare.repayWithCollateral(
FolksCore.getProvider<ChainType.EVM>(folksChain.folksChainId),
convertFromGenericAddress(userAddress, folksChain.chainType),
messageToSend,
network,
accountId,
loanId,
folksTokenId,
amount,
spokeChain,
);
default:
return exhaustiveCheck(folksChain.chainType);
}
},
};

export const write = {
Expand Down Expand Up @@ -781,6 +858,33 @@ export const write = {
return exhaustiveCheck(folksChain.chainType);
}
},

async repayWithCollateral(
accountId: AccountId,
loanId: LoanId,
folksTokenId: FolksTokenId,
amount: bigint,
prepareCall: PrepareRepayWithCollateralCall,
) {
const folksChain = FolksCore.getSelectedFolksChain();

const { poolId } = getHubTokenData(folksTokenId, folksChain.network);

switch (folksChain.chainType) {
case ChainType.EVM:
return await FolksEvmLoan.write.repayWithCollateral(
FolksCore.getProvider<ChainType.EVM>(folksChain.folksChainId),
FolksCore.getSigner<ChainType.EVM>(),
accountId,
loanId,
poolId,
amount,
prepareCall,
);
default:
return exhaustiveCheck(folksChain.chainType);
}
},
};

export const read = {
Expand Down

0 comments on commit a7babf4

Please sign in to comment.