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: support safe account cancel tx #1762

Merged
merged 7 commits into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 33 additions & 5 deletions _raw/locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,24 @@
"trustValue": "Trust value",
"importedDelegatedAddress": "Imported delegated address",
"noDelegatedAddress": "No imported delegated address",
"coboSafeNotPermission": "This delegate address does not have permission to initiate this transaction"
"coboSafeNotPermission": "This delegate address does not have permission to initiate this transaction",
"SafeNonceSelector": {
"explain": {
"contractCall": "Contract Call",
"send": "Send Token",
"unknown": "Unknown Transaction"
},
"optionGroup": {
"recommendTitle": "Recommended nonce",
"replaceTitle": "Replace the transaction in Queue "
},
"option": {
"new": "New Transaction"
},
"error": {
"pendingList": "Fail to load pending transactions, <1/><2>Retry</2>"
}
}
},
"signFooterBar": {
"requestFrom": "Request from",
Expand Down Expand Up @@ -1386,9 +1403,19 @@
"approvalExplain": "Approve {{count}} {{token}} for {{protocol}}",
"unlimited": "unlimited",
"action": {
"send": "Send"
},
"viewBtn": "View"
"send": "Send",
"cancel": "Cancel Pending Transaction"
},
"viewBtn": "View",
"replaceBtn": "Replace",
"ReplacePopup": {
"options": {
"send": "Send Token",
"reject": "Reject Transaction"
},
"title": "Select how to replace this transaction",
"desc": " A signed transaction cannot be removed but it can be replaced with a new transaction with the same nonce."
}
},
"importSuccess": {
"title": "Imported Successfully",
Expand Down Expand Up @@ -1604,7 +1631,8 @@
"Loading": "Loading",
"nonce": "nonce",
"Balance": "Balance",
"Done": "Done"
"Done": "Done",
"Nonce": "Nonce"
},
"background": {
"error": {
Expand Down
25 changes: 22 additions & 3 deletions _raw/locales/zh_CN/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
"Loading": "加载中",
"Balance": "余额",
"Done": "完成",
"nonce": "nonce"
"nonce": "nonce",
"Nonce": "Nonce"
},
"page": {
"transactions": {
Expand Down Expand Up @@ -1215,7 +1216,16 @@
"wrapToken": "Wrap 代币",
"contractPopularity": "No.{{0}} on {{1}}",
"myMarkWithContract": "My mark on {{chainName}} contract",
"coboSafeNotPermission": "This delegate address does not have permission to initiate this transaction"
"coboSafeNotPermission": "This delegate address does not have permission to initiate this transaction",
"SafeNonceSelector": {
"optionGroup": {
"recommendTitle": "推荐的Nonce",
"replaceTitle": "替换Queue中的交易"
},
"error": {
"pendingList": "Pending列表获取失败, <1/><2>重试</2>"
}
}
},
"signTypedData": {
"buyNFT": {
Expand Down Expand Up @@ -1417,7 +1427,16 @@
"action": {
"send": "发送"
},
"viewBtn": "查看"
"viewBtn": "查看",
"replaceBtn": "替换",
"ReplacePopup": {
"title": "请选择替换交易的方式",
"desc": "已经签名的交易无法被清除,但是可以通过发起一笔相同 Nonce的交易来替换。",
"options": {
"send": "发送代币",
"reject": "拒绝交易"
}
}
},
"importSuccess": {
"title": "成功导入",
Expand Down
12 changes: 12 additions & 0 deletions src/background/controller/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1521,6 +1521,18 @@ export class WalletController extends BaseController {
};
};

getGnosisPendingTxs = async (address: string, networkId: string) => {
if (!networkId) {
return [];
}
const safe = await createSafeService({
networkId: networkId,
address,
});
const { results } = await safe.getPendingTransactions();
return results;
};

getGnosisOwners = async (
account: Account,
safeAddress: string,
Expand Down
11 changes: 11 additions & 0 deletions src/ui/assets/safe-nonce-select/checked.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/ui/assets/safe-nonce-select/down.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions src/ui/assets/safe-nonce-select/find.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/ui/assets/safe-nonce-select/unchecked.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions src/ui/views/Approval/components/Actions/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1389,3 +1389,30 @@ export const getActionTypeText = (data: ParsedActionData) => {
}
return t('page.signTx.unknownAction');
};

export const getActionTypeTextByType = (type: string) => {
const t = i18n.t;

const dict = {
swap_token: t('page.signTx.swap.title'),
cross_token: t('page.signTx.crossChain.title'),
cross_swap_token: t('page.signTx.swapAndCross.title'),
send_token: t('page.signTx.send.title'),
approve_token: t('page.signTx.tokenApprove.title'),
revoke_token: t('page.signTx.revokeTokenApprove.title'),
permit2_revoke_token: t('page.signTx.revokePermit2.title'),
wrap_token: t('page.signTx.wrapToken'),
unwrap_token: t('page.signTx.unwrap'),
send_nft: t('page.signTx.sendNFT.title'),
approve_nft: t('page.signTx.nftApprove.title'),
revoke_nft: t('page.signTx.revokeNFTApprove.title'),
approve_collection: t('page.signTx.nftCollectionApprove.title'),
revoke_collection: t('page.signTx.revokeNFTCollectionApprove.title'),
deploy_contract: t('page.signTx.deployContract.title'),
cancel_tx: t('page.signTx.cancelTx.title'),
push_multisig: t('page.signTx.submitMultisig.title'),
contract_call: t('page.signTx.contractCall.title'),
};

return dict[type] || t('page.signTx.unknownAction');
};
1 change: 1 addition & 0 deletions src/ui/views/Approval/components/FooterBar/FooterBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ const Shadow = styled.div`
rgba(175, 175, 175, 0.168147) 41.66%,
rgba(130, 130, 130, 0.35) 83.44%
);
z-index: 10;
`;

const ChainLogo = styled.img`
Expand Down
99 changes: 59 additions & 40 deletions src/ui/views/Approval/components/SignTx.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ import { TokenDetailPopup } from '@/ui/views/Dashboard/components/TokenDetailPop
import { useSignPermissionCheck } from '../hooks/useSignPermissionCheck';
import { useTestnetCheck } from '../hooks/useTestnetCheck';
import { CoboDelegatedDrawer } from './TxComponents/CoboDelegatedDrawer';
import { SafeNonceSelector } from './TxComponents/SafeNonceSelector';

interface BasicCoboArgusInfo {
address: string;
Expand Down Expand Up @@ -821,6 +822,7 @@ const SignTx = ({ params, origin }: SignTxProps) => {
isSend,
isSwap,
isViewGnosisSafe,
safeTxGas,
} = normalizeTxParams(params.data[0]);

let updateNonce = true;
Expand Down Expand Up @@ -1124,6 +1126,7 @@ const SignTx = ({ params, origin }: SignTxProps) => {
to: tx.to,
data: tx.data,
value: tx.value,
safeTxGas: safeTxGas,
};
params.nonce = realNonce;
await wallet.buildGnosisTransaction(
Expand All @@ -1139,6 +1142,7 @@ const SignTx = ({ params, origin }: SignTxProps) => {
data: [account.address, JSON.stringify(typedData)],
session: params.session,
isGnosis: true,
isSend,
account: account,
method: 'ethSignTypedDataV4',
uiRequestComponent: 'SignTypedData',
Expand Down Expand Up @@ -1838,45 +1842,58 @@ const SignTx = ({ params, origin }: SignTxProps) => {
engineResults={engineResults}
/>
)}
<GasSelector
disabled={isGnosisAccount || isCoboArugsAccount}
isReady={isReady}
gasLimit={gasLimit}
noUpdate={isCancel || isSpeedUp}
gasList={gasList}
selectedGas={selectedGas}
version={txDetail.pre_exec_version}
gas={{
error: txDetail.gas.error,
success: txDetail.gas.success,
gasCostUsd: gasExplainResponse.gasCostUsd,
gasCostAmount: gasExplainResponse.gasCostAmount,
}}
gasCalcMethod={(price) => {
return explainGas({
gasUsed,
gasPrice: price,
chainId,
nativeTokenPrice: txDetail?.native_token.price || 0,
tx,
wallet,
gasLimit,
});
}}
recommendGasLimit={recommendGasLimit}
recommendNonce={recommendNonce}
chainId={chainId}
onChange={handleGasChange}
nonce={realNonce || tx.nonce}
disableNonce={isSpeedUp || isCancel}
is1559={support1559}
isHardware={isHardware}
manuallyChangeGasLimit={manuallyChangeGasLimit}
errors={checkErrors}
engineResults={engineResults}
nativeTokenBalance={nativeTokenBalance}
gasPriceMedian={gasPriceMedian}
/>
{isGnosisAccount ? (
<SafeNonceSelector
isReady={isReady}
chainId={chainId}
value={realNonce}
safeInfo={safeInfo}
onChange={(v) => {
setRealNonce(v);
setNonceChanged(true);
}}
/>
) : (
<GasSelector
disabled={isGnosisAccount || isCoboArugsAccount}
isReady={isReady}
gasLimit={gasLimit}
noUpdate={isCancel || isSpeedUp}
gasList={gasList}
selectedGas={selectedGas}
version={txDetail.pre_exec_version}
gas={{
error: txDetail.gas.error,
success: txDetail.gas.success,
gasCostUsd: gasExplainResponse.gasCostUsd,
gasCostAmount: gasExplainResponse.gasCostAmount,
}}
gasCalcMethod={(price) => {
return explainGas({
gasUsed,
gasPrice: price,
chainId,
nativeTokenPrice: txDetail?.native_token.price || 0,
tx,
wallet,
gasLimit,
});
}}
recommendGasLimit={recommendGasLimit}
recommendNonce={recommendNonce}
chainId={chainId}
onChange={handleGasChange}
nonce={realNonce || tx.nonce}
disableNonce={isSpeedUp || isCancel}
is1559={support1559}
isHardware={isHardware}
manuallyChangeGasLimit={manuallyChangeGasLimit}
errors={checkErrors}
engineResults={engineResults}
nativeTokenBalance={nativeTokenBalance}
gasPriceMedian={gasPriceMedian}
/>
)}
</>
)}
{isGnosisAccount && safeInfo && (
Expand Down Expand Up @@ -1952,7 +1969,9 @@ const SignTx = ({ params, origin }: SignTxProps) => {
(isLedger && !useLedgerLive && !hasConnectedLedgerHID) ||
!canProcess ||
!!checkErrors.find((item) => item.level === 'forbidden') ||
hasUnProcessSecurityResult
hasUnProcessSecurityResult ||
(isGnosisAccount &&
new BigNumber(realNonce || 0).isLessThan(safeInfo?.nonce || 0))
}
/>
</>
Expand Down
9 changes: 8 additions & 1 deletion src/ui/views/Approval/components/SignTypedData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ interface SignTypedDataProps {
name: string;
};
isGnosis?: boolean;
isSend?: boolean;
account?: Account;
}

Expand Down Expand Up @@ -144,7 +145,7 @@ const SignTypedData = ({ params }: { params: SignTypedDataProps }) => {
}
}, [engineResults, currentTx]);

const { data, session, method, isGnosis, account } = params;
const { data, session, method, isGnosis, isSend, account } = params;
let parsedMessage = '';
let _message = '';
try {
Expand Down Expand Up @@ -315,6 +316,9 @@ const SignTypedData = ({ params }: { params: SignTypedDataProps }) => {
version: 'V4',
}
);
if (isSend) {
wallet.clearPageStateCache();
}
resolveApproval({
uiRequestComponent: WaitingSignMessageComponent[params.account.type],
type: params.account.type,
Expand Down Expand Up @@ -344,6 +348,9 @@ const SignTypedData = ({ params }: { params: SignTypedDataProps }) => {
await wallet.gnosisAddSignature(params.account.address, result);
await wallet.postGnosisTransaction();
}
if (isSend) {
wallet.clearPageStateCache();
}
resolveApproval(result, false, true);
} catch (e) {
message.error(e.message);
Expand Down
Loading