Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connext integration #3

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open

Conversation

prathmeshkhandelwal1
Copy link
Collaborator

  • updated PR having the final piece of code
  • Need testing for deposit on hub contract
  • added UI for selecting polygon chain for going cross-chain

@prathmeshkhandelwal1 prathmeshkhandelwal1 changed the title Connext inetgration Connext integration May 3, 2023
@@ -160,7 +166,9 @@
"url": "^0.11.0",
"uuid": "^9.0.0",
"wagmi": "^0.12.7",
"web3modal": "^1.9.3"
"web3modal": "^1.9.3",
"zlib": "^1.0.5",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are all of these new dependencies needed?

@@ -724,4 +724,68 @@ export const getGhTokenListLogoUrl = (chainId: number, address: string) =>
// oasis: 42262,

export const UNSUPPORTED_WAGMI_CHAIN = [122, 128, 106, 42262];

export const SUPPORTED_CHAINS_BY_CONNEXT: Record<number, { domainId: string; name: string; network: string }> = {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could extend de NetworkStruct type to add the domainId, and with that you would already have if it is mainnet or a testnet, plus all the names. Furthermore, i would assign keys here as [NETWORKS.optimism.chainId]

@@ -363,15 +367,21 @@ const Swap = ({
),
});
trackEvent('DCA - Create position submitting');
const result = await positionService.deposit(
// change it to xCall here.
// eslint-disable-next-line no-console
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please don't disable these lint-rules, its fine if it fails the lint action since later you can remove them

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted ✅

@@ -179,14 +182,16 @@ export default class Web3Service {
this.providerService,
this.safeService
);
this.connextService = new ConnextService(this.walletService, 137); // hardcoding polygon ID
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how would this work if its not just polygon? do we need a connextService for each chain?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, we are only demonstrating arbitrum to polygon transfer as of now, this will be changed to dynamic input later after discussing the UX

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should remove the second parameter right? Since its going to depend on when you create the position

@@ -0,0 +1,15 @@
import { DestinationCallDataParams } from '@connext/chain-abstraction/dist/types';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets create a connext.ts file inside utils to send all of these new utils

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works

// get the pool fees.
const poolFee = await this.connextService.getPoolFeeForUniV3Helper(
destinantionDomainID, // Destination Domain
destinantionUSDC, // final destination token, Address should be getting from user
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all of this is harcoded only for USDC, could we make so it accepts any token?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Underlying it's using USDC , we claim for any to any token as, On origin side : <any_token> -> USDC, then bridge this USDC to destination chain using connext and then again USDC -> <any_token> on destinantion

const relayerFees = await this.connextService.getCalculatedRelayerFees(originDomainID, destinantionDomainID);

// swap can be done after figuring out about domains, and also after deploying contract
const amountIn = BigNumber.from('40000000000000');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait why is this hardcoded?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for MVP

@@ -645,6 +655,16 @@ export default class PositionService {
if (yieldFrom || yieldTo) {
permissions = [...permissions, PERMISSIONS.TERMINATE];
}
const POLYGON_WETH = '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619';

const forwardCallData = getForwardFunctionCallHelper(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this would only be needed in case of using multichain right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

@@ -742,6 +834,35 @@ export default class PositionService {
return this.safeService.submitMultipleTxs([approveTx, depositTx]);
}

async xCallDeposit(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer if we keep it all under the deposit function, the consumers of the positionService should have no need to know if it is a normal deposit or an xCallDeposit, and we can query different functions based on the destination network.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bump, from what I've said before about accepting a fundWithToken that is of Token type. If the from.chainId !== fundWithToken.chainId then we go through xCall, if not, we go through the normal flow

@@ -19,6 +19,7 @@ import TokenIcon from 'common/token-icon';
import useSelectedNetwork from 'hooks/useSelectedNetwork';
import Select from '@mui/material/Select';
import MenuItem from '@mui/material/MenuItem';
import { Button } from '@mui/material';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use our button please from @common/components/button

Copy link

@FiboApe FiboApe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall seems pretty simple, but we should start generalizing the services, we can handle the UX later

@prathmeshkhandelwal1
Copy link
Collaborator Author

For all those Hardcoded values like network (i.e polygon) , we are only enabling cross-chain from arbitrum network to polygon network in this PR, which is underlying uses USDC to make bridging happen. This is majorly for MVP and after UI discussion we can convert all the hardcoded values as a input from user or mean SDK.

@prathmeshkhandelwal1 prathmeshkhandelwal1 linked an issue May 18, 2023 that may be closed by this pull request
Copy link

@FiboApe FiboApe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove all the UI stuff, and I think there still a few leftover comments from the previous review

};

export const X_TARGET_ADDRESS: Record<number, string> = {
137: '0xC825d25123Ca8d49066cf8F0AeE164660056e172',
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be updated with the new chains?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, If we deploy target on more chain, We have to add that particular contract address here.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool lets update it, in an ideal world tho, this would be exposed directly by the connext sdk right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think so, as It totally is on-chain, and people will have their own adapter contract, so they have to keep track of contract address on chains which they are moving to.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh gotcha, this is a specific Mean Finance adapter with connext?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

}

getRPCURL(chainID: number) {
const network = Object.values(NETWORKS).find((net) => net.chainId === chainID);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we already have lodash, so you can use their find function which is a bit more legible find(NETWORKS, { chainId }

.map(([key, value]) => ({ domainId: value.domainId, chainId: key }));

domainChainIds.forEach((obj) => {
domainConfig[obj.domainId] = { providers: [this.getRPCURL(parseInt(obj.chainId, 10)) as string] };
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should check that this.getRPCUrl actually does return something in case it could find the chainId


const sdkConfig: SdkConfig = {
signerAddress: this.walletService.account as string,
network: 'mainnet', // can change it to testnet as well
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this parameter for?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For initing the connext core SDK

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right but I mean, what does it imply if it is "mainnet"? or "testnet"? shouldn't it work the same regardless of what type of network it is?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So for initialising the SDK we have to define if this is for mainnet or testnet. If we define any env for the environment we can modify it according to that!

.map(([key, value]) => ({ domainId: value.domainId, chainId: key }));

domainChainIds.forEach((obj) => {
domainConfig[obj.domainId] = { providers: [this.getRPCURL(parseInt(obj.chainId, 10)) as string] };
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, we should check that this.getRpcUrl at least returns something


const forwardCallData = getForwardFunctionCallHelper(
destinantionUSDC as string, // destination USDC
POLYGON_WETH.address, // destinantion token
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be generalized right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bump

yieldFromPossible?: string,
yieldToPossible?: string
) {
const destinantionUSDC = this.connextService.getNativeUSDCAddress(destinantionChainID);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would this actually be destinationUSDC? or it should be the token I want to get on the destination chain?, btw typo on destination

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be destination USDC or any other token which we support underlying the bridge, i.e USDC, DAI, USDT or WETH

So the flow is -
Origin token -> Asset we support for bridging (USDC, USDT, DAI or WETH) -> Same asset on destination after bridge -> final token (after destination swap)

In this flow its the third one.

yieldFromPossible,
yieldToPossible,
destinantionUSDC,
destinantionChainID
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same typo here

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bump

const destinantionCallDataParams = getDestinationCallDataParams(
this.walletService.account as string,
destinantionUSDC, // to the token on destination
poolFee as string
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so getDestinationCallDataParams should take that into account, or fail here in case poolFee is not an accepted value

this.walletService.account as string
);

return this.providerService.sendTransaction(txRequest as TransactionRequest);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then we should check for the txRequest being undefined

@@ -0,0 +1,394 @@
import React from 'react';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can remove this file :)

@@ -0,0 +1,1171 @@
import React from 'react';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

@@ -0,0 +1,203 @@
import * as React from 'react';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

swapForwarderData: {
toAsset: token,
swapData: {
amountOutMin: '0',
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be 0 or should the value change?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine

@@ -179,14 +182,16 @@ export default class Web3Service {
this.providerService,
this.safeService
);
this.connextService = new ConnextService(this.walletService, 137); // hardcoding polygon ID
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should remove the second parameter right? Since its going to depend on when you create the position

const POLYGON_WETH = getWrappedProtocolToken(destinationChainID as number);

const forwardCallData = getForwardFunctionCallHelper(
destinationUSDC as string, // destination USDC
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

destinationUSDC seems to be very specific for the connext integration, could we abstract that there?

yieldFromPossible?: string,
yieldToPossible?: string
) {
const destinationUSDC = this.connextService.getNativeUSDCAddress(destinantionChainID);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo on destinantion

yieldFromPossible,
yieldToPossible,
destinantionUSDC,
destinantionChainID
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bump

const xTargetAddress = X_TARGET_ADDRESS[destinantionChainID]; // polygon address for mean target

const chainID = (await this.providerService.getNetwork()).chainId;
const DestinationToken = getWrappedProtocolToken(destinantionChainID); // can have any address in UI for destination
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then lets accept a new parameter for this function that is fundWithToken which is a Token and is the address of the token that we are going to fund it with.

The Token type already has a chainid so you can infer it from there and not have to pass a specific chain as a parameter

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I think from parameter is the same, Cant we use chainID from from parameter and can do like if(from.chainID !== to.chainID).

@@ -742,6 +834,35 @@ export default class PositionService {
return this.safeService.submitMultipleTxs([approveTx, depositTx]);
}

async xCallDeposit(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bump, from what I've said before about accepting a fundWithToken that is of Token type. If the from.chainId !== fundWithToken.chainId then we go through xCall, if not, we go through the normal flow

Comment on lines +19 to +31
const domainConfig: { [domainId: string]: { providers: string[] } } = {};

const domainChainIds = Object.entries(SUPPORTED_CHAINS_BY_CONNEXT)
.filter(([key]) => typeof key === 'number')
.map(([key, value]) => ({ domainId: value.domainId, chainId: key }));

domainChainIds.forEach((obj) => {
domainConfig[obj.domainId] = { providers: [this.getRPCURL(parseInt(obj.chainId, 10))] };
});

const sdkConfig: SdkConfig = {
signerAddress: this.walletService.getAccount(),
network: 'mainnet', // can change it to testnet as well
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I woudl move this all into its own function, since walletService.getAccount() will return the current account and at the moment of the constructor the wallet is not yet connected, so its always going to be empty.

The idea would be that on the setAccount method of the web3Service.ts we call that function to regenerate the config with the new address

@@ -629,6 +643,16 @@ export default class PositionService {
if (yieldFrom || yieldTo) {
permissions = [...permissions, PERMISSIONS.TERMINATE];
}
const destinationToken = getWrappedProtocolToken(destinationChainID as number);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this would actually just be the from

const xTargetAddress = X_TARGET_ADDRESS[destinationChainID]; // polygon address for mean target

const chainID = (await this.providerService.getNetwork()).chainId;
const DestinationToken = getWrappedProtocolToken(destinationChainID); // can have any address in UI for destination
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should just be the from right?


const destinantionCallDataParams = getDestinationCallDataParams(
this.walletService.getAccount(),
destinationUSDC, // to the token on destination
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be the to of the position?

const swapAndXCallParams = getSwapAndXcallParams(
originDomainID,
destinantionDomainID,
fromToken.address,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this would be the fundWithToken right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Mean Suggested Changes
2 participants