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

feat: bridge #2388

Merged
merged 20 commits into from
Jul 12, 2024
Merged
65 changes: 63 additions & 2 deletions _raw/locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -795,7 +795,7 @@
"slippage-adjusted-refresh-quote": "Slippage adjusted. Refresh quote.",
"price-expired-refresh-quote": "Price expired. Refresh quote.",
"approve-x-symbol": "Approve {{symbol}}",
"approve-and-swap": "Approve and Swap",
"approve-and-swap": "Approve and Swap via {{name}}",
"swap-via-x": "Swap via {{name}}",
"get-quotes": "Get quotes",
"chain": "Chain",
Expand All @@ -805,6 +805,10 @@
"amount-in": "Amount in {{symbol}}",
"unlimited-allowance": "Unlimited allowance",
"insufficient-balance": "Insufficient balance",
"hidden-no-quote-rates_one": "Hidden {{count}} no-quote rate",
"hidden-no-quote-rates_other": "Hidden {{count}} no-quote rates",

"Gas-fee-too-high": "Gas fee too high",
"rabby-fee": "Rabby fee",
"preferMEV": "Prefer MEV Guarded",
"preferMEVTip": "Enable \"MEV Guarded\" feature for Ethereum swaps to reduce sandwich attack risks. Note: this feature is not supported if you use a custom RPC or wallet connect address",
Expand Down Expand Up @@ -854,6 +858,62 @@
"estimate": "Estimate:",
"actual": "Actual:"
},
"bridge": {
"title": "Bridge",
"history": "Bridge history",
"the-following-bridge-route-are-found": "Found following bridge route",
"no-transaction-records": "No transaction records",
"pendingTip": "Tx submitted. If the tx is pending for long hours, you can try to clear pending in settings.",
"Pending": "Pending",
"completedTip": "Transaction on chain, decoding data to generate record",
"Completed": "Completed",
"estimate": "Estimate:",
"actual": "Actual:",
"gas-fee": "GasFee: {{gasUsed}}",
"gas-x-price": "Gas price: {{price}} Gwei.",
"detail-tx": "Detail",
"unlimited-allowance": "Unlimited allowance",
"insufficient-balance": "Insufficient balance",
"bridgeTo": "Bridge To",
"BridgeTokenPair": "Bridge Token Pair",
"tokenPairPlaceholder": "Select Token Pair",
"Amount": "Amount",
"getRoutes": "Get routes",
"slippage-adjusted-refresh-quote": "Slippage adjusted. Refresh route.",
"price-expired-refresh-route": "Price expired. Refresh route.",
"approve-x-symbol": "Approve {{symbol}}",
"approve-and-bridge": "Approve and Bridge on {{name}}",
"need-to-approve-token-before-bridge": "Need to approve token before bridge",
"via-bridge": "via {{bridge}}",
"duration": "{{duration}} min",
"estimated-value": "≈ {{value}}",
"best": "Best",
"bridge-cost": "Bridge cost",
"rabby-fee": "Rabby fee",
"bridge-via-x": "Bridge on {{name}}",
"no-route-found": "No route found",
"aggregator-not-enabled": "This aggregator is not enabled to trade by you.",
"enable-it": "Enable it",

"settingModal": {
"title": "Enable Bridge Aggregators to trade",
"confirm": "Confirm",
"SupportedBridge": "Supported Bridge:",
"confirmModal": {
"title": "Enable Trading with this Aggregator",
"tip1": "1. Once enabled, you will interact directly with the contract from this aggregator.",
"tip2": "2. Rabby is not liable for any risks arising from the contract of this aggregator",
"i-understand-and-accept-it": "I understand and accept it"
}
},
"tokenPairDrawer": {
"title": "Select from supported token pair",
"tokenPair": "Token Pair",
"balance": "Balance Value",
"noData": "No Supported Token Pair"
}
},

"manageAddress": {
"no-address": "No address",
"no-match": "No match",
Expand Down Expand Up @@ -912,7 +972,8 @@
"rabbyPoints": "Rabby Points",
"more": "More",
"manageAddress": "Manage Address",
"nft": "NFT"
"nft": "NFT",
"bridge": "Bridge"
},
"comingSoon": "Coming soon",
"soon": "Soon",
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@
"@rabby-wallet/eth-watch-keyring": "1.0.0",
"@rabby-wallet/gnosis-sdk": "1.3.6",
"@rabby-wallet/page-provider": "0.3.5",
"@rabby-wallet/rabby-api": "0.7.22",
"@rabby-wallet/rabby-api": "0.7.23",
"@rabby-wallet/rabby-security-engine": "2.0.3",
"@rabby-wallet/rabby-swap": "0.0.37",
"@rabby-wallet/rabby-swap": "0.0.38",
"@rabby-wallet/widgets": "1.0.9",
"@rematch/core": "2.2.0",
"@rematch/select": "3.1.2",
Expand Down
2 changes: 2 additions & 0 deletions src/background/controller/provider/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
swapService,
transactionBroadcastWatchService,
notificationService,
bridgeService,
} from 'background/service';
import { Session } from 'background/service/session';
import { Tx, TxPushType } from 'background/service/openapi';
Expand Down Expand Up @@ -503,6 +504,7 @@ class ProviderController extends BaseController {

if (hash) {
swapService.postSwap(chain, hash, other);
bridgeService.postBridge(chain, hash, other);
}

statsData.submit = true;
Expand Down
129 changes: 128 additions & 1 deletion src/background/controller/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
transactionBroadcastWatchService,
RabbyPointsService,
HDKeyRingLastAddAddrTimeService,
bridgeService,
} from 'background/service';
import buildinProvider, {
EthereumProvider,
Expand Down Expand Up @@ -104,6 +105,7 @@ import { matomoRequestEvent } from '@/utils/matomo-request';
import { BALANCE_LOADING_CONFS } from '@/constant/timeout';
import { IExtractFromPromise } from '@/ui/utils/type';
import { Wallet, thirdparty } from '@ethereumjs/wallet';
import { BridgeRecord } from '../service/bridge';

const stashKeyrings: Record<string | number, any> = {};

Expand Down Expand Up @@ -523,6 +525,115 @@ export class WalletController extends BaseController {
}
};

bridgeToken = async (
{
to,
data,
payTokenRawAmount,
payTokenId,
payTokenChainServerId,
shouldApprove,
shouldTwoStepApprove,
gasPrice,
info,
value,
}: {
data: string;
to: string;
value: string;
chainId: number;
shouldApprove: boolean;
shouldTwoStepApprove: boolean;
payTokenId: string;
payTokenChainServerId: string;
payTokenRawAmount: string;
gasPrice?: number;
info: BridgeRecord;
},
$ctx?: any
) => {
const account = await preferenceService.getCurrentAccount();
if (!account) throw new Error(t('background.error.noCurrentAccount'));
const chainObj = findChain({ serverId: payTokenChainServerId });
if (!chainObj)
throw new Error(
t('background.error.notFindChain', { payTokenChainServerId })
);
try {
if (shouldTwoStepApprove) {
unTriggerTxCounter.increase(3);
await this.approveToken(
payTokenChainServerId,
payTokenId,
to,
0,
{
ga: {
...$ctx?.ga,
source: 'approvalAndBridge|tokenApproval',
},
},
gasPrice,
{ isBridge: true }
);
unTriggerTxCounter.decrease();
}

if (shouldApprove) {
if (!shouldTwoStepApprove) {
unTriggerTxCounter.increase(2);
}
await this.approveToken(
payTokenChainServerId,
payTokenId,
to,
payTokenRawAmount,
{
ga: {
...$ctx?.ga,
source: 'approvalAndBridge|tokenApproval',
},
},
gasPrice,
{ isBridge: true }
);
unTriggerTxCounter.decrease();
}

if (info) {
bridgeService.addTx(chainObj.enum, data, info);
}
await this.sendRequest({
$ctx:
shouldApprove && payTokenId !== chainObj.nativeTokenAddress
? {
ga: {
...$ctx?.ga,
source: 'approvalAndBridge|bridge',
},
}
: $ctx,
method: 'eth_sendTransaction',
params: [
{
from: account.address,
to: to,
data: data || '0x',
value: `0x${new BigNumber(value || '0').toString(16)}`,
chainId: chainObj.id,
gasPrice: gasPrice
? `0x${new BigNumber(gasPrice).toString(16)}`
: undefined,
isBridge: true,
},
],
});
unTriggerTxCounter.decrease();
} catch (e) {
unTriggerTxCounter.reset();
}
};

getUnTriggerTxCount = () => {
return unTriggerTxCounter.count;
};
Expand Down Expand Up @@ -581,7 +692,11 @@ export class WalletController extends BaseController {
amount: number | string,
$ctx?: any,
gasPrice?: number,
extra?: { isSwap: boolean; swapPreferMEVGuarded?: boolean }
extra?: {
isSwap?: boolean;
swapPreferMEVGuarded?: boolean;
isBridge?: boolean;
}
) => {
const account = await preferenceService.getCurrentAccount();
if (!account) throw new Error(t('background.error.noCurrentAccount'));
Expand Down Expand Up @@ -1243,6 +1358,18 @@ export class WalletController extends BaseController {
addHDKeyRingLastAddAddrTime = HDKeyRingLastAddAddrTimeService.addUnixRecord;
getHDKeyRingLastAddAddrTimeStore = HDKeyRingLastAddAddrTimeService.getStore;

getBridgeData = bridgeService.getBridgeData;
getBridgeAggregators = bridgeService.getBridgeAggregators;
setBridgeAggregators = bridgeService.setBridgeAggregators;
getBridgeUnlimitedAllowance = bridgeService.getUnlimitedAllowance;
setBridgeUnlimitedAllowance = bridgeService.setUnlimitedAllowance;
setBridgeSelectedChain = bridgeService.setSelectedChain;
setBridgeSelectedFromToken = bridgeService.setSelectedFromToken;
setBridgeSelectedToToken = bridgeService.setSelectedToToken;
getBridgeSortIncludeGasFee = bridgeService.getBridgeSortIncludeGasFee;
setBridgeSortIncludeGasFee = bridgeService.setBridgeSortIncludeGasFee;
setBridgeSettingFirstOpen = bridgeService.setBridgeSettingFirstOpen;

setCustomRPC = RPCService.setRPC;
removeCustomRPC = RPCService.removeCustomRPC;
getAllCustomRPC = RPCService.getAllRPC;
Expand Down
2 changes: 2 additions & 0 deletions src/background/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
securityEngineService,
transactionBroadcastWatchService,
HDKeyRingLastAddAddrTimeService,
bridgeService,
} from './service';
import { providerController, walletController } from './controller';
import { getOriginFromUrl } from '@/utils';
Expand Down Expand Up @@ -97,6 +98,7 @@ async function restoreAppState() {
await securityEngineService.init();
await RabbyPointsService.init();
await HDKeyRingLastAddAddrTimeService.init();
await bridgeService.init();

setPopupIcon(
walletController.isUnlocked() || !walletController.isBooted()
Expand Down
Loading
Loading