diff --git a/lang/default.json b/lang/default.json index ec07a834b3..e16faadfdb 100644 --- a/lang/default.json +++ b/lang/default.json @@ -49,6 +49,10 @@ "+ixiPI": { "defaultMessage": "Delete moment" }, + "+jt4rV": { + "defaultMessage": "Claim USDT support", + "description": "src/components/Transaction/index.tsx" + }, "+o9W2T": { "defaultMessage": "File upload failed, please verify the file link is valid, or manually download and upload again.", "description": "UNABLE_TO_UPLOAD_FROM_URL" @@ -134,9 +138,6 @@ "defaultMessage": "Matters ID has been set up. More account info can be found in Settings", "description": "src/components/Dialogs/SetUserNameDialog/ConfirmStep.tsx" }, - "0HdNPs": { - "defaultMessage": "{link1}: In order to increase the sources of income for creators, Matters introduced {link2} and {link3}, enabling the payer and the payee to conduct transactions in different currencies. Through {link4}, and other services you can acqure a {link6}, and receive payments from {link7}, applicable on both Matters website and IPFS." - }, "0JlaP1": { "defaultMessage": "Oops!This link has expired", "description": "src/views/Callback/UI.tsx" @@ -274,6 +275,9 @@ "defaultMessage": "Disconnect", "description": "src/components/Dialogs/RemoveSocialLoginDialog/Content.tsx" }, + "2Sgvfr": { + "defaultMessage": "USDT {amount} pending claim" + }, "2W0f9h": { "defaultMessage": "Bio" }, @@ -389,9 +393,6 @@ "4nHH2x": { "defaultMessage": "Applied successfully" }, - "4tqFCR": { - "defaultMessage": "The author has not bound the USDT wallet yet" - }, "4wOWfp": { "defaultMessage": "What's this?", "description": "src/components/Billboard/index.tsx" @@ -479,6 +480,9 @@ "6BbPcY": { "defaultMessage": "The comment has been forcibly hidden" }, + "6Bxl4S": { + "defaultMessage": "Claim {amount} USDT failed. Click here to retry or contact ask@matters.town" + }, "6CQaLH": { "defaultMessage": "Please select or enter amount" }, @@ -503,6 +507,9 @@ "defaultMessage": "subscribers_empty", "description": "src/views/Circle/Analytics/SubscriberAnalytics/index.tsx" }, + "6Sj2lN": { + "defaultMessage": "Claim" + }, "6Vznnt": { "defaultMessage": "left a comment in your circle", "description": "src/components/Notice/CircleNotice/CircleNewDiscussionComments.tsx" @@ -702,6 +709,10 @@ "9Vkz9W": { "defaultMessage": "Maximum image area is limited to 100 megapixels (for example, 10,000×10,000 pixels)." }, + "9WMs5q": { + "defaultMessage": "Connect", + "description": "src/views/Me/Wallet/Balance" + }, "9WRlF4": { "defaultMessage": "Send" }, @@ -843,6 +854,9 @@ "defaultMessage": "Provide support funds to", "description": "src/components/Forms/PaymentForm/PaymentInfo/index.tsx" }, + "C/4nS6": { + "defaultMessage": "Connect and claim" + }, "C3NKBg": { "defaultMessage": "Connected to {type}", "description": "src/views/Me/Settings/Settings/Socials/index.tsx" @@ -872,6 +886,12 @@ "defaultMessage": "Copy comment", "description": "src/components/Comment/DropdownActions/index.tsx" }, + "CcVXhc": { + "defaultMessage": "Matters is sending {amount} to your connected wallet {address} via a contract transaction (Matters will temporarily cover the transaction fee). For assistance, please contact ask@matters.town" + }, + "CgPGAu": { + "defaultMessage": ", connect your wallet to claim" + }, "Ci7dxf": { "defaultMessage": "Comment deleted", "description": "src/components/Notice/NoticeComment.tsx/moment" @@ -1133,6 +1153,9 @@ "HAlOn1": { "defaultMessage": "Name" }, + "HBdVkS": { + "defaultMessage": "Claiming in progress" + }, "HBxXD/": { "defaultMessage": "License" }, @@ -1143,6 +1166,9 @@ "HJ0iZJ": { "defaultMessage": "Confirm Archiving" }, + "HJsl78": { + "defaultMessage": "An issue occurred while claiming USDT. Please retry or contact ask@matters.town" + }, "HPVOw/": { "defaultMessage": "Wallet", "description": "src/views/Me/Settings/Settings/index.tsx" @@ -1232,9 +1258,6 @@ "IpMWC4": { "defaultMessage": "You’ve posted several times in a short period. Please take a break." }, - "Is5PqP": { - "defaultMessage": "Interledger Protocol" - }, "ItUuuX": { "defaultMessage": "invites you to join the circle {circleName} , and you can experience it for {freePeriod} days for free", "description": "src/components/Notice/CircleNotice/CircleInvitationNotice.tsx" @@ -1385,9 +1408,6 @@ "defaultMessage": "Article published", "description": "src/views/Me/DraftDetail/PublishState/PublishedState.tsx" }, - "LklXfd": { - "defaultMessage": "Payment Pointer" - }, "LmiUWG": { "defaultMessage": "You do not have permissionn to perform this operation", "description": "FORBIDDEN_BY_TARGET_STATE" @@ -1518,6 +1538,9 @@ "O7ozeo": { "defaultMessage": "Update profile" }, + "ODncRd": { + "defaultMessage": "Claiming..." + }, "OIj8pQ": { "defaultMessage": "Invitation Sent", "description": "src/views/Circle/Settings/ManageInvitation/AddInvitationDialog/Sent.tsx" @@ -1955,16 +1978,10 @@ "WQT8ZA": { "defaultMessage": "Edit collection" }, - "WiGHyF": { - "defaultMessage": "Web Monetization standard" - }, "WpvsPu": { "defaultMessage": "Subscribe", "description": "src/views/Circle/Analytics/SubscriberAnalytics/index.tsx" }, - "WrQjnc": { - "defaultMessage": "Payment pointer updated" - }, "WsPbZT": { "defaultMessage": "Continue payout" }, @@ -1989,6 +2006,10 @@ "XOEFDf": { "defaultMessage": "{total} articles" }, + "XQ9bi3": { + "defaultMessage": "More", + "description": "src/components/Dialogs/WithdrawVaultUSDTDialog/Content.tsx" + }, "XQTBu6": { "defaultMessage": "mentioned you in your circle broadcast comment", "description": "src/components/Notice/CircleNotice/CircleNewBroadcastComments.tsx" @@ -2321,6 +2342,9 @@ "defaultMessage": "No blocked users yet", "description": "src/views/Me/Settings/Blocked/SettingsBlocked.tsx" }, + "dK7Dnj": { + "defaultMessage": "🔥 Claim for free" + }, "dQhNbF": { "defaultMessage": "Payment will be processed by Stripe, allowing your support to be unrestricted by region.", "description": "src/components/Forms/PaymentForm/StripeCheckout/index.tsx" @@ -2332,6 +2356,9 @@ "dTOtPO": { "defaultMessage": "Top Up" }, + "dUkC8R": { + "defaultMessage": "Claim USDT" + }, "dVbKzB": { "defaultMessage": "Comments and replies", "description": "src/views/Me/Settings/Notifications/GeneralSettings/index.tsx" @@ -2435,6 +2462,9 @@ "defaultMessage": "Pending", "description": "src/views/Circle/Settings/ManageInvitation/Invites/index.tsx" }, + "fko+MR": { + "defaultMessage": "Retry claiming" + }, "fnv5rD": { "defaultMessage": "like article (current {total} likes)" }, @@ -2512,6 +2542,9 @@ "hBLCwn": { "defaultMessage": "other amount" }, + "hDDFgp": { + "defaultMessage": "Matters will send {amount} to your connected wallet {address} via a contract transaction (Matters will temporarily cover the transaction fee). For assistance, please contact ask@matters.town" + }, "hG2cBH": { "defaultMessage": "Subscribe Circle" }, @@ -2544,9 +2577,6 @@ "i4OBEw": { "defaultMessage": "\"{name}\" is invalid." }, - "i7cXnf": { - "defaultMessage": "The wallet address starts with \"$\"." - }, "iEJeQH": { "defaultMessage": "Liker ID" }, @@ -2769,6 +2799,10 @@ "mBkZcw": { "defaultMessage": "Like moment" }, + "mBmmr+": { + "defaultMessage": "Subscribed", + "description": "src/views/User/UserProfile/FollowingDialog/CirclesFeed/CirclesTabs/index.tsx" + }, "mCAIcg": { "defaultMessage": "Hottest", "description": "src/views/Circle/Analytics/ContentAnalytics/index.tsx" @@ -2803,6 +2837,9 @@ "ml3SZN": { "defaultMessage": "Minimum 8 characters. Uppercase/lowercase letters, numbers and symbols are allowed" }, + "mm2UAM": { + "defaultMessage": "Connect wallet and claim USDT" + }, "mp9SBo": { "defaultMessage": "Circle notifications", "description": "src/views/Me/Settings/Notifications/index.tsx" @@ -2830,6 +2867,9 @@ "defaultMessage": "My profile", "description": "src/views/Me/Settings/Settings/MyProfile/index.tsx" }, + "n3SsO1": { + "defaultMessage": "The contract has sent {amount} to the linked wallet. Click here for details." + }, "n3shsQ": { "defaultMessage": "Invalid name", "description": "NAME_INVALID" @@ -2845,6 +2885,10 @@ "defaultMessage": "replied your comment in", "description": "src/components/Notice/CommentCommentNotice/CommentNewReplyNotice.tsx" }, + "nVoVnb": { + "defaultMessage": "Followed", + "description": "src/views/User/UserProfile/FollowingDialog/CirclesFeed/CirclesTabs/index.tsx" + }, "nWhqw9": { "defaultMessage": "Publish Now" }, @@ -2890,9 +2934,6 @@ "defaultMessage": "liked", "description": "src/components/Notice/ArticleNotice/ArticleNewAppreciationNotice.tsx" }, - "p6D+Uc": { - "defaultMessage": "Enter Payment Pointer" - }, "p9gEZh": { "defaultMessage": "Up to 3 images can be uploaded" }, @@ -3002,12 +3043,18 @@ "defaultMessage": "Unavailable", "description": "FORBIDDEN_BY_STATE" }, + "rAFb3E": { + "defaultMessage": "Matters will send {amount} to your connected wallet via a contract transaction (Matters will temporarily cover the transaction fee)." + }, "rDX3h6": { "defaultMessage": "Version Description" }, "rE7sE3": { "defaultMessage": "CC0 License" }, + "rG2xmp": { + "defaultMessage": "Claim successful" + }, "rHi+cL": { "defaultMessage": "Most readers", "description": "src/views/Me/Works/Published/SortTabs.tsx" @@ -3252,9 +3299,6 @@ "defaultMessage": "reset your login password", "description": "src/components/Dialogs/SetEmailDialog/Content.tsx" }, - "vyG38g": { - "defaultMessage": "wallet address" - }, "w+6UiO": { "defaultMessage": "Add Invitation" }, diff --git a/lang/en.json b/lang/en.json index 828e86a159..244068e004 100644 --- a/lang/en.json +++ b/lang/en.json @@ -49,6 +49,10 @@ "+ixiPI": { "defaultMessage": "Delete moment" }, + "+jt4rV": { + "defaultMessage": "Claim USDT support", + "description": "src/components/Transaction/index.tsx" + }, "+o9W2T": { "defaultMessage": "File upload failed, please verify the file link is valid, or manually download and upload again.", "description": "UNABLE_TO_UPLOAD_FROM_URL" @@ -134,9 +138,6 @@ "defaultMessage": "Matters ID has been set up. More account info can be found in Settings", "description": "src/components/Dialogs/SetUserNameDialog/ConfirmStep.tsx" }, - "0HdNPs": { - "defaultMessage": "{link1}: In order to increase the sources of income for creators, Matters introduced {link2} and {link3}, enabling the payer and the payee to conduct transactions in different currencies. Through {link4}, and other services you can acqure a {link6}, and receive payments from {link7}, applicable on both Matters website and IPFS." - }, "0JlaP1": { "defaultMessage": "Oops!This link has expired", "description": "src/views/Callback/UI.tsx" @@ -274,6 +275,9 @@ "defaultMessage": "Disconnect", "description": "src/components/Dialogs/RemoveSocialLoginDialog/Content.tsx" }, + "2Sgvfr": { + "defaultMessage": "USDT {amount} pending claim" + }, "2W0f9h": { "defaultMessage": "Bio" }, @@ -389,9 +393,6 @@ "4nHH2x": { "defaultMessage": "Applied successfully" }, - "4tqFCR": { - "defaultMessage": "The author has not bound the USDT wallet yet" - }, "4wOWfp": { "defaultMessage": "What's this?", "description": "src/components/Billboard/index.tsx" @@ -479,6 +480,9 @@ "6BbPcY": { "defaultMessage": "The comment has been forcibly hidden" }, + "6Bxl4S": { + "defaultMessage": "Claim {amount} USDT failed. Click here to retry or contact ask@matters.town" + }, "6CQaLH": { "defaultMessage": "Please select or enter amount" }, @@ -503,6 +507,9 @@ "defaultMessage": "subscribers_empty", "description": "src/views/Circle/Analytics/SubscriberAnalytics/index.tsx" }, + "6Sj2lN": { + "defaultMessage": "Claim" + }, "6Vznnt": { "defaultMessage": "left a comment in your circle", "description": "src/components/Notice/CircleNotice/CircleNewDiscussionComments.tsx" @@ -702,6 +709,10 @@ "9Vkz9W": { "defaultMessage": "Maximum image area is limited to 100 megapixels (for example, 10,000×10,000 pixels)." }, + "9WMs5q": { + "defaultMessage": "Connect", + "description": "src/views/Me/Wallet/Balance" + }, "9WRlF4": { "defaultMessage": "Send" }, @@ -843,6 +854,9 @@ "defaultMessage": "Provide support funds to", "description": "src/components/Forms/PaymentForm/PaymentInfo/index.tsx" }, + "C/4nS6": { + "defaultMessage": "Connect and claim" + }, "C3NKBg": { "defaultMessage": "Connected to {type}", "description": "src/views/Me/Settings/Settings/Socials/index.tsx" @@ -872,6 +886,12 @@ "defaultMessage": "Copy comment", "description": "src/components/Comment/DropdownActions/index.tsx" }, + "CcVXhc": { + "defaultMessage": "Matters is sending {amount} to your connected wallet {address} via a contract transaction (Matters will temporarily cover the transaction fee). For assistance, please contact ask@matters.town" + }, + "CgPGAu": { + "defaultMessage": ", connect your wallet to claim" + }, "Ci7dxf": { "defaultMessage": "Comment deleted", "description": "src/components/Notice/NoticeComment.tsx/moment" @@ -1133,6 +1153,9 @@ "HAlOn1": { "defaultMessage": "Name" }, + "HBdVkS": { + "defaultMessage": "Claiming in progress" + }, "HBxXD/": { "defaultMessage": "License" }, @@ -1143,6 +1166,9 @@ "HJ0iZJ": { "defaultMessage": "Confirm Archiving" }, + "HJsl78": { + "defaultMessage": "An issue occurred while claiming USDT. Please retry or contact ask@matters.town" + }, "HPVOw/": { "defaultMessage": "Wallet", "description": "src/views/Me/Settings/Settings/index.tsx" @@ -1232,9 +1258,6 @@ "IpMWC4": { "defaultMessage": "You’ve posted several times in a short period. Please take a break." }, - "Is5PqP": { - "defaultMessage": "Interledger Protocol" - }, "ItUuuX": { "defaultMessage": "invites you to join the circle {circleName} , and you can experience it for {freePeriod} days for free", "description": "src/components/Notice/CircleNotice/CircleInvitationNotice.tsx" @@ -1385,9 +1408,6 @@ "defaultMessage": "Article published", "description": "src/views/Me/DraftDetail/PublishState/PublishedState.tsx" }, - "LklXfd": { - "defaultMessage": "Payment Pointer" - }, "LmiUWG": { "defaultMessage": "You do not have permissionn to perform this operation", "description": "FORBIDDEN_BY_TARGET_STATE" @@ -1518,6 +1538,9 @@ "O7ozeo": { "defaultMessage": "Update profile" }, + "ODncRd": { + "defaultMessage": "Claiming..." + }, "OIj8pQ": { "defaultMessage": "Invitation Sent", "description": "src/views/Circle/Settings/ManageInvitation/AddInvitationDialog/Sent.tsx" @@ -1955,16 +1978,10 @@ "WQT8ZA": { "defaultMessage": "Edit collection" }, - "WiGHyF": { - "defaultMessage": "Web Monetization standard" - }, "WpvsPu": { "defaultMessage": "Subscribe", "description": "src/views/Circle/Analytics/SubscriberAnalytics/index.tsx" }, - "WrQjnc": { - "defaultMessage": "Payment pointer updated" - }, "WsPbZT": { "defaultMessage": "Continue payout" }, @@ -1989,6 +2006,10 @@ "XOEFDf": { "defaultMessage": "{total} articles" }, + "XQ9bi3": { + "defaultMessage": "More", + "description": "src/components/Dialogs/WithdrawVaultUSDTDialog/Content.tsx" + }, "XQTBu6": { "defaultMessage": "mentioned you in your circle broadcast comment", "description": "src/components/Notice/CircleNotice/CircleNewBroadcastComments.tsx" @@ -2321,6 +2342,9 @@ "defaultMessage": "No blocked users yet", "description": "src/views/Me/Settings/Blocked/SettingsBlocked.tsx" }, + "dK7Dnj": { + "defaultMessage": "🔥 Claim for free" + }, "dQhNbF": { "defaultMessage": "Payment will be processed by Stripe, allowing your support to be unrestricted by region.", "description": "src/components/Forms/PaymentForm/StripeCheckout/index.tsx" @@ -2332,6 +2356,9 @@ "dTOtPO": { "defaultMessage": "Top Up" }, + "dUkC8R": { + "defaultMessage": "Claim USDT" + }, "dVbKzB": { "defaultMessage": "Comments and replies", "description": "src/views/Me/Settings/Notifications/GeneralSettings/index.tsx" @@ -2435,6 +2462,9 @@ "defaultMessage": "Pending", "description": "src/views/Circle/Settings/ManageInvitation/Invites/index.tsx" }, + "fko+MR": { + "defaultMessage": "Retry claiming" + }, "fnv5rD": { "defaultMessage": "like article (current {total} likes)" }, @@ -2512,6 +2542,9 @@ "hBLCwn": { "defaultMessage": "other amount" }, + "hDDFgp": { + "defaultMessage": "Matters will send {amount} to your connected wallet {address} via a contract transaction (Matters will temporarily cover the transaction fee). For assistance, please contact ask@matters.town" + }, "hG2cBH": { "defaultMessage": "Subscribe Circle" }, @@ -2544,9 +2577,6 @@ "i4OBEw": { "defaultMessage": "\"{name}\" is invalid." }, - "i7cXnf": { - "defaultMessage": "The wallet address starts with \"$\"." - }, "iEJeQH": { "defaultMessage": "Liker ID" }, @@ -2769,6 +2799,10 @@ "mBkZcw": { "defaultMessage": "Like moment" }, + "mBmmr+": { + "defaultMessage": "Subscribed", + "description": "src/views/User/UserProfile/FollowingDialog/CirclesFeed/CirclesTabs/index.tsx" + }, "mCAIcg": { "defaultMessage": "Hottest", "description": "src/views/Circle/Analytics/ContentAnalytics/index.tsx" @@ -2803,6 +2837,9 @@ "ml3SZN": { "defaultMessage": "Minimum 8 characters. Uppercase/lowercase letters, numbers and symbols are allowed" }, + "mm2UAM": { + "defaultMessage": "Connect wallet and claim USDT" + }, "mp9SBo": { "defaultMessage": "Circle notifications", "description": "src/views/Me/Settings/Notifications/index.tsx" @@ -2830,6 +2867,9 @@ "defaultMessage": "My profile", "description": "src/views/Me/Settings/Settings/MyProfile/index.tsx" }, + "n3SsO1": { + "defaultMessage": "The contract has sent {amount} to the linked wallet. Click here for details." + }, "n3shsQ": { "defaultMessage": "Invalid name", "description": "NAME_INVALID" @@ -2845,6 +2885,10 @@ "defaultMessage": "replied your comment in", "description": "src/components/Notice/CommentCommentNotice/CommentNewReplyNotice.tsx" }, + "nVoVnb": { + "defaultMessage": "Followed", + "description": "src/views/User/UserProfile/FollowingDialog/CirclesFeed/CirclesTabs/index.tsx" + }, "nWhqw9": { "defaultMessage": "Publish Now" }, @@ -2890,9 +2934,6 @@ "defaultMessage": "liked", "description": "src/components/Notice/ArticleNotice/ArticleNewAppreciationNotice.tsx" }, - "p6D+Uc": { - "defaultMessage": "Enter Payment Pointer" - }, "p9gEZh": { "defaultMessage": "Up to 3 images can be uploaded" }, @@ -3002,12 +3043,18 @@ "defaultMessage": "Unavailable", "description": "FORBIDDEN_BY_STATE" }, + "rAFb3E": { + "defaultMessage": "Matters will send {amount} to your connected wallet via a contract transaction (Matters will temporarily cover the transaction fee)." + }, "rDX3h6": { "defaultMessage": "Version Description" }, "rE7sE3": { "defaultMessage": "CC0 License" }, + "rG2xmp": { + "defaultMessage": "Claim successful" + }, "rHi+cL": { "defaultMessage": "Most readers", "description": "src/views/Me/Works/Published/SortTabs.tsx" @@ -3252,9 +3299,6 @@ "defaultMessage": "reset your login password", "description": "src/components/Dialogs/SetEmailDialog/Content.tsx" }, - "vyG38g": { - "defaultMessage": "wallet address" - }, "w+6UiO": { "defaultMessage": "Add Invitation" }, diff --git a/lang/zh-Hans.json b/lang/zh-Hans.json index 011fb4c6cf..d8bd88749b 100644 --- a/lang/zh-Hans.json +++ b/lang/zh-Hans.json @@ -49,6 +49,10 @@ "+ixiPI": { "defaultMessage": "删除动态" }, + "+jt4rV": { + "defaultMessage": "提領支持", + "description": "src/components/Transaction/index.tsx" + }, "+o9W2T": { "defaultMessage": "文件上传失败,请确认文件链接是否有效,或手动下载后再上传", "description": "UNABLE_TO_UPLOAD_FROM_URL" @@ -87,7 +91,7 @@ "defaultMessage": "支持排行榜" }, "/NX9L+": { - "defaultMessage": "确认授权", + "defaultMessage": "去钱包确认", "description": "src/components/Forms/PaymentForm/PayTo/Confirm/index.tsx" }, "/TXBJR": { @@ -95,7 +99,7 @@ "description": "UNKNOWN_ERROR" }, "/cyuh2": { - "defaultMessage": "前往授权" + "defaultMessage": "去钱包授权" }, "/dKzfc": { "defaultMessage": "该作品因违反社区约章,已被站方强制封存。" @@ -134,9 +138,6 @@ "defaultMessage": "Matters ID 已设置,更多帐号相关设置可前往设置页修改", "description": "src/components/Dialogs/SetUserNameDialog/ConfirmStep.tsx" }, - "0HdNPs": { - "defaultMessage": "{link1}:为增加创作者的收入来源,Matters 引入了 {link2} 与 {link3},实现付款方与收款方即使使用不同的货币进行交易,也可以对交易进行自动币种转换。你可以通过 {link4}等服务配置 {link6},获得来自 {link7} 平台的收入,在 Matters 网站与 IPFS 网络中均可使用。" - }, "0JlaP1": { "defaultMessage": "Oops!链接已失效", "description": "src/views/Callback/UI.tsx" @@ -274,6 +275,9 @@ "defaultMessage": "解绑", "description": "src/components/Dialogs/RemoveSocialLoginDialog/Content.tsx" }, + "2Sgvfr": { + "defaultMessage": "USDT {amount} 待提领" + }, "2W0f9h": { "defaultMessage": "个人简介" }, @@ -389,9 +393,6 @@ "4nHH2x": { "defaultMessage": "报名成功" }, - "4tqFCR": { - "defaultMessage": "作者尚未启用 USDT 钱包" - }, "4wOWfp": { "defaultMessage": "这是什么?", "description": "src/components/Billboard/index.tsx" @@ -479,6 +480,9 @@ "6BbPcY": { "defaultMessage": "评论已被强制隐藏" }, + "6Bxl4S": { + "defaultMessage": "提领支持金额({amount} USDT)时遇到问题,点此重试或联系 ask@matters.town" + }, "6CQaLH": { "defaultMessage": "请选择或输入金额" }, @@ -503,6 +507,9 @@ "defaultMessage": "目前总订阅人数", "description": "src/views/Circle/Analytics/SubscriberAnalytics/index.tsx" }, + "6Sj2lN": { + "defaultMessage": "提领支持" + }, "6Vznnt": { "defaultMessage": "在你的围炉中留言", "description": "src/components/Notice/CircleNotice/CircleNewDiscussionComments.tsx" @@ -702,6 +709,10 @@ "9Vkz9W": { "defaultMessage": "图片面积不得超过 1 亿像素(如 10,000 x 10,000 像素)" }, + "9WMs5q": { + "defaultMessage": "绑定钱包", + "description": "src/views/Me/Wallet/Balance" + }, "9WRlF4": { "defaultMessage": "送出" }, @@ -843,6 +854,9 @@ "defaultMessage": "递出支持资金给", "description": "src/components/Forms/PaymentForm/PaymentInfo/index.tsx" }, + "C/4nS6": { + "defaultMessage": "绑定并提领" + }, "C3NKBg": { "defaultMessage": "{type} 已绑定", "description": "src/views/Me/Settings/Settings/Socials/index.tsx" @@ -872,6 +886,12 @@ "defaultMessage": "复制留言", "description": "src/components/Comment/DropdownActions/index.tsx" }, + "CcVXhc": { + "defaultMessage": "Matters 正在通过合约交易将 {amount} 发送至你绑定的钱包 {address}(Matters 将暂时承担交易手续费)。如需帮助请联系 ask@matters.town" + }, + "CgPGAu": { + "defaultMessage": ",绑定钱包后可领取" + }, "Ci7dxf": { "defaultMessage": "留言已删除", "description": "src/components/Notice/NoticeComment.tsx/moment" @@ -1133,6 +1153,9 @@ "HAlOn1": { "defaultMessage": "用户名" }, + "HBdVkS": { + "defaultMessage": "正在提领支持" + }, "HBxXD/": { "defaultMessage": "版权声明" }, @@ -1143,6 +1166,9 @@ "HJ0iZJ": { "defaultMessage": "确认归档" }, + "HJsl78": { + "defaultMessage": "提领支持金额时遇到问题,请重试或联系 ask@matters.town" + }, "HPVOw/": { "defaultMessage": "数字钱包", "description": "src/views/Me/Settings/Settings/index.tsx" @@ -1232,9 +1258,6 @@ "IpMWC4": { "defaultMessage": "短时间内已发布多条动态,请先休息一会吧~" }, - "Is5PqP": { - "defaultMessage": "跨账本协议" - }, "ItUuuX": { "defaultMessage": "邀你加入围炉 {circleName} ,你可以免费体验 {freePeriod} 天", "description": "src/components/Notice/CircleNotice/CircleInvitationNotice.tsx" @@ -1385,9 +1408,6 @@ "defaultMessage": "作品已发布", "description": "src/views/Me/DraftDetail/PublishState/PublishedState.tsx" }, - "LklXfd": { - "defaultMessage": "跨链收款地址" - }, "LmiUWG": { "defaultMessage": "你无法对此对象进行该操作", "description": "FORBIDDEN_BY_TARGET_STATE" @@ -1518,6 +1538,9 @@ "O7ozeo": { "defaultMessage": "修改个人资料" }, + "ODncRd": { + "defaultMessage": "提领中..." + }, "OIj8pQ": { "defaultMessage": "成功发送邀请", "description": "src/views/Circle/Settings/ManageInvitation/AddInvitationDialog/Sent.tsx" @@ -1955,16 +1978,10 @@ "WQT8ZA": { "defaultMessage": "编辑选集" }, - "WiGHyF": { - "defaultMessage": "Web Monetization 标准" - }, "WpvsPu": { "defaultMessage": "订阅", "description": "src/views/Circle/Analytics/SubscriberAnalytics/index.tsx" }, - "WrQjnc": { - "defaultMessage": "收款地址已更新" - }, "WsPbZT": { "defaultMessage": "继续提现" }, @@ -1989,6 +2006,10 @@ "XOEFDf": { "defaultMessage": "{total} 篇作品" }, + "XQ9bi3": { + "defaultMessage": "详情", + "description": "src/components/Dialogs/WithdrawVaultUSDTDialog/Content.tsx" + }, "XQTBu6": { "defaultMessage": "在你的围炉广播中留言提及你", "description": "src/components/Notice/CircleNotice/CircleNewBroadcastComments.tsx" @@ -2300,7 +2321,7 @@ "defaultMessage": "返回" }, "d1mBsg": { - "defaultMessage": "新订阅者", + "defaultMessage": "关注的围炉", "description": "src/views/Me/Settings/Notifications/Circle/index.tsx" }, "d4waan": { @@ -2321,6 +2342,9 @@ "defaultMessage": "尚无屏蔽记录", "description": "src/views/Me/Settings/Blocked/SettingsBlocked.tsx" }, + "dK7Dnj": { + "defaultMessage": "🔥 免费提领" + }, "dQhNbF": { "defaultMessage": "付款将由 Stripe 处理,让你的支持不受地域限制", "description": "src/components/Forms/PaymentForm/StripeCheckout/index.tsx" @@ -2332,6 +2356,9 @@ "dTOtPO": { "defaultMessage": "储值" }, + "dUkC8R": { + "defaultMessage": "提领支持" + }, "dVbKzB": { "defaultMessage": "评论和回复", "description": "src/views/Me/Settings/Notifications/GeneralSettings/index.tsx" @@ -2435,6 +2462,9 @@ "defaultMessage": "邀请中", "description": "src/views/Circle/Settings/ManageInvitation/Invites/index.tsx" }, + "fko+MR": { + "defaultMessage": "重试提领" + }, "fnv5rD": { "defaultMessage": "赞赏作品(当前 {total} 次赞赏)" }, @@ -2512,6 +2542,9 @@ "hBLCwn": { "defaultMessage": "其他金额" }, + "hDDFgp": { + "defaultMessage": "Matters 会通过合约交易将 {amount} 发送至你绑定的钱包 {address}(Matters 将暂时承担交易手续费)。如需帮助请联系 ask@matters.town" + }, "hG2cBH": { "defaultMessage": "订阅围炉" }, @@ -2544,9 +2577,6 @@ "i4OBEw": { "defaultMessage": "不能使用 “{name}”" }, - "i7cXnf": { - "defaultMessage": "钱包地址以“$”开头" - }, "iEJeQH": { "defaultMessage": "设置 Liker ID" }, @@ -2769,6 +2799,10 @@ "mBkZcw": { "defaultMessage": "喜欢动态" }, + "mBmmr+": { + "defaultMessage": "订阅", + "description": "src/views/User/UserProfile/FollowingDialog/CirclesFeed/CirclesTabs/index.tsx" + }, "mCAIcg": { "defaultMessage": "站内阅读热门排行", "description": "src/views/Circle/Analytics/ContentAnalytics/index.tsx" @@ -2803,6 +2837,9 @@ "ml3SZN": { "defaultMessage": "至少 8 个字符,支持英文大小写字母、数字和特殊符号" }, + "mm2UAM": { + "defaultMessage": "綁定錢包並提領支持" + }, "mp9SBo": { "defaultMessage": "围炉通知", "description": "src/views/Me/Settings/Notifications/index.tsx" @@ -2830,6 +2867,9 @@ "defaultMessage": "个人信息", "description": "src/views/Me/Settings/Settings/MyProfile/index.tsx" }, + "n3SsO1": { + "defaultMessage": "交易合约已将金额 {amount} 发送至绑定钱包,点此查看详情" + }, "n3shsQ": { "defaultMessage": "名称不正确", "description": "NAME_INVALID" @@ -2845,6 +2885,10 @@ "defaultMessage": "在 ", "description": "src/components/Notice/CommentCommentNotice/CommentNewReplyNotice.tsx" }, + "nVoVnb": { + "defaultMessage": "关注", + "description": "src/views/User/UserProfile/FollowingDialog/CirclesFeed/CirclesTabs/index.tsx" + }, "nWhqw9": { "defaultMessage": "立即发布" }, @@ -2890,9 +2934,6 @@ "defaultMessage": "赞赏了", "description": "src/components/Notice/ArticleNotice/ArticleNewAppreciationNotice.tsx" }, - "p6D+Uc": { - "defaultMessage": "请输入地址" - }, "p9gEZh": { "defaultMessage": "动态最多支持 3 张图片" }, @@ -3002,12 +3043,18 @@ "defaultMessage": "不可用", "description": "FORBIDDEN_BY_STATE" }, + "rAFb3E": { + "defaultMessage": "Matters 会通过合约交易将 {amount} 发送到你绑定的钱包(Matters 将暂时承担交易手续费)。" + }, "rDX3h6": { "defaultMessage": "版本简述" }, "rE7sE3": { "defaultMessage": "CC0 公众领域贡献宣告" }, + "rG2xmp": { + "defaultMessage": "提领成功" + }, "rHi+cL": { "defaultMessage": "最多读者", "description": "src/views/Me/Works/Published/SortTabs.tsx" @@ -3252,9 +3299,6 @@ "defaultMessage": "重置你的登录密码", "description": "src/components/Dialogs/SetEmailDialog/Content.tsx" }, - "vyG38g": { - "defaultMessage": "钱包地址" - }, "w+6UiO": { "defaultMessage": "新增邀请" }, diff --git a/lang/zh-Hant.json b/lang/zh-Hant.json index 3fc2c247c0..81a2690a6b 100644 --- a/lang/zh-Hant.json +++ b/lang/zh-Hant.json @@ -49,6 +49,10 @@ "+ixiPI": { "defaultMessage": "刪除動態" }, + "+jt4rV": { + "defaultMessage": "提領支持", + "description": "src/components/Transaction/index.tsx" + }, "+o9W2T": { "defaultMessage": "檔案上傳失敗,請確認檔案連結是否有效,或手動下載後再上傳", "description": "UNABLE_TO_UPLOAD_FROM_URL" @@ -87,7 +91,7 @@ "defaultMessage": "支持排行榜" }, "/NX9L+": { - "defaultMessage": "確認授權", + "defaultMessage": "去錢包確認", "description": "src/components/Forms/PaymentForm/PayTo/Confirm/index.tsx" }, "/TXBJR": { @@ -95,7 +99,7 @@ "description": "UNKNOWN_ERROR" }, "/cyuh2": { - "defaultMessage": "前往授權" + "defaultMessage": "去錢包授權" }, "/dKzfc": { "defaultMessage": "該作品因違反社區約章,已被站方強制歸檔。" @@ -134,9 +138,6 @@ "defaultMessage": "Matters ID 已設置,更多帳號相關設置可前往設定頁修改", "description": "src/components/Dialogs/SetUserNameDialog/ConfirmStep.tsx" }, - "0HdNPs": { - "defaultMessage": "{link1}:為增加創作者的收入來源,Matters 引入了 {link2} 與 {link3},實現付款方與收款方即使使用不同的貨幣進行交易,也可以對交易進行自動幣種轉換。你可以通過 {link4}等服務配置 {link6},獲得來自 {link7} 平臺的收入,在 Matters 網站與 IPFS 網絡中均可使用。" - }, "0JlaP1": { "defaultMessage": "Oops!連結已失效", "description": "src/views/Callback/UI.tsx" @@ -274,6 +275,9 @@ "defaultMessage": "解綁", "description": "src/components/Dialogs/RemoveSocialLoginDialog/Content.tsx" }, + "2Sgvfr": { + "defaultMessage": "USDT {amount} 待提領" + }, "2W0f9h": { "defaultMessage": "個人簡介" }, @@ -389,9 +393,6 @@ "4nHH2x": { "defaultMessage": "報名成功" }, - "4tqFCR": { - "defaultMessage": "作者尚未啓用 USDT 錢包" - }, "4wOWfp": { "defaultMessage": "這是什麼?", "description": "src/components/Billboard/index.tsx" @@ -479,6 +480,9 @@ "6BbPcY": { "defaultMessage": "因違反社區約章,評論已被隱藏" }, + "6Bxl4S": { + "defaultMessage": "提領支持金額({amount} USDT)時遇到問題,點此重試或聯繫 ask@matters.town" + }, "6CQaLH": { "defaultMessage": "請選擇或輸入金額" }, @@ -503,6 +507,9 @@ "defaultMessage": "目前總訂閱人數", "description": "src/views/Circle/Analytics/SubscriberAnalytics/index.tsx" }, + "6Sj2lN": { + "defaultMessage": "提領支持" + }, "6Vznnt": { "defaultMessage": "在你的圍爐中留言", "description": "src/components/Notice/CircleNotice/CircleNewDiscussionComments.tsx" @@ -702,6 +709,10 @@ "9Vkz9W": { "defaultMessage": "圖片面積不得超過 1 億像素(如 10,000x10,000 像素)" }, + "9WMs5q": { + "defaultMessage": "綁定錢包", + "description": "src/views/Me/Wallet/Balance" + }, "9WRlF4": { "defaultMessage": "送出" }, @@ -843,6 +854,9 @@ "defaultMessage": "遞出支持資金給", "description": "src/components/Forms/PaymentForm/PaymentInfo/index.tsx" }, + "C/4nS6": { + "defaultMessage": "綁定並提領" + }, "C3NKBg": { "defaultMessage": "{type} 已綁定", "description": "src/views/Me/Settings/Settings/Socials/index.tsx" @@ -872,6 +886,12 @@ "defaultMessage": "複製留言", "description": "src/components/Comment/DropdownActions/index.tsx" }, + "CcVXhc": { + "defaultMessage": "Matters 正在通過合約交易將 {amount} 發送至你綁定的錢包 {address}(Matters 將暫時承擔交易手續費)。如需幫助請聯繫 ask@matters.town" + }, + "CgPGAu": { + "defaultMessage": ",連接錢包領取" + }, "Ci7dxf": { "defaultMessage": "留言已刪除", "description": "src/components/Notice/NoticeComment.tsx/moment" @@ -1133,6 +1153,9 @@ "HAlOn1": { "defaultMessage": "用戶名" }, + "HBdVkS": { + "defaultMessage": "正在提領支持" + }, "HBxXD/": { "defaultMessage": "版權聲明" }, @@ -1143,6 +1166,9 @@ "HJ0iZJ": { "defaultMessage": "確認封存" }, + "HJsl78": { + "defaultMessage": "提領支持金額時遇到問題,請重試或聯繫 ask@matters.town" + }, "HPVOw/": { "defaultMessage": "數字錢包", "description": "src/views/Me/Settings/Settings/index.tsx" @@ -1232,9 +1258,6 @@ "IpMWC4": { "defaultMessage": "短時間內已發布多條動態,請先休息一會吧~" }, - "Is5PqP": { - "defaultMessage": "跨賬本協議" - }, "ItUuuX": { "defaultMessage": "邀你加入圍爐 {circleName} ,你可以免費體驗 {freePeriod} 天", "description": "src/components/Notice/CircleNotice/CircleInvitationNotice.tsx" @@ -1385,9 +1408,6 @@ "defaultMessage": "作品已發布", "description": "src/views/Me/DraftDetail/PublishState/PublishedState.tsx" }, - "LklXfd": { - "defaultMessage": "跨鏈收款地址" - }, "LmiUWG": { "defaultMessage": "你無法對此對象進行該操作", "description": "FORBIDDEN_BY_TARGET_STATE" @@ -1518,6 +1538,9 @@ "O7ozeo": { "defaultMessage": "修改個人資料" }, + "ODncRd": { + "defaultMessage": "提領中..." + }, "OIj8pQ": { "defaultMessage": "成功發送邀請", "description": "src/views/Circle/Settings/ManageInvitation/AddInvitationDialog/Sent.tsx" @@ -1955,16 +1978,10 @@ "WQT8ZA": { "defaultMessage": "編輯選集" }, - "WiGHyF": { - "defaultMessage": "Web Monetization 標準" - }, "WpvsPu": { "defaultMessage": "訂閱", "description": "src/views/Circle/Analytics/SubscriberAnalytics/index.tsx" }, - "WrQjnc": { - "defaultMessage": "收款地址已更新" - }, "WsPbZT": { "defaultMessage": "繼續提現" }, @@ -1989,6 +2006,10 @@ "XOEFDf": { "defaultMessage": "{total} 篇作品" }, + "XQ9bi3": { + "defaultMessage": "詳情", + "description": "src/components/Dialogs/WithdrawVaultUSDTDialog/Content.tsx" + }, "XQTBu6": { "defaultMessage": "在你的圍爐廣播中留言提及你", "description": "src/components/Notice/CircleNotice/CircleNewBroadcastComments.tsx" @@ -2321,6 +2342,9 @@ "defaultMessage": "尚無封鎖紀錄", "description": "src/views/Me/Settings/Blocked/SettingsBlocked.tsx" }, + "dK7Dnj": { + "defaultMessage": "🔥 免費提領" + }, "dQhNbF": { "defaultMessage": "付款將由 Stripe 處理,讓你的支持不受地域限制", "description": "src/components/Forms/PaymentForm/StripeCheckout/index.tsx" @@ -2332,6 +2356,9 @@ "dTOtPO": { "defaultMessage": "儲值" }, + "dUkC8R": { + "defaultMessage": "提領支持" + }, "dVbKzB": { "defaultMessage": "評論和回覆", "description": "src/views/Me/Settings/Notifications/GeneralSettings/index.tsx" @@ -2435,6 +2462,9 @@ "defaultMessage": "邀請中", "description": "src/views/Circle/Settings/ManageInvitation/Invites/index.tsx" }, + "fko+MR": { + "defaultMessage": "重試提領" + }, "fnv5rD": { "defaultMessage": "讚賞作品(當前 {total} 次讚賞)" }, @@ -2512,6 +2542,9 @@ "hBLCwn": { "defaultMessage": "其他金額" }, + "hDDFgp": { + "defaultMessage": "Matters 會通過合約交易將 {amount} 發送至你綁定的錢包 {address}(Matters 將暫時承擔交易手續費)。如需幫助請聯繫 ask@matters.town" + }, "hG2cBH": { "defaultMessage": "訂閱圍爐" }, @@ -2544,9 +2577,6 @@ "i4OBEw": { "defaultMessage": "不能使用「{name}」" }, - "i7cXnf": { - "defaultMessage": "錢包地址以「$」開頭" - }, "iEJeQH": { "defaultMessage": "設置 Liker ID" }, @@ -2769,6 +2799,10 @@ "mBkZcw": { "defaultMessage": "喜歡動態" }, + "mBmmr+": { + "defaultMessage": "訂閱", + "description": "src/views/User/UserProfile/FollowingDialog/CirclesFeed/CirclesTabs/index.tsx" + }, "mCAIcg": { "defaultMessage": "站內閱讀熱門排行", "description": "src/views/Circle/Analytics/ContentAnalytics/index.tsx" @@ -2803,6 +2837,9 @@ "ml3SZN": { "defaultMessage": "至少 8 個字元,支持英文大小寫字母、數字和特殊符號" }, + "mm2UAM": { + "defaultMessage": "綁定錢包並提領支持" + }, "mp9SBo": { "defaultMessage": "圍爐通知", "description": "src/views/Me/Settings/Notifications/index.tsx" @@ -2830,6 +2867,9 @@ "defaultMessage": "個人資料", "description": "src/views/Me/Settings/Settings/MyProfile/index.tsx" }, + "n3SsO1": { + "defaultMessage": "交易合約已將金額 {amount} 發送至綁定錢包,點此查看詳情" + }, "n3shsQ": { "defaultMessage": "名稱不正確", "description": "NAME_INVALID" @@ -2845,6 +2885,10 @@ "defaultMessage": "在", "description": "src/components/Notice/CommentCommentNotice/CommentNewReplyNotice.tsx" }, + "nVoVnb": { + "defaultMessage": "追蹤", + "description": "src/views/User/UserProfile/FollowingDialog/CirclesFeed/CirclesTabs/index.tsx" + }, "nWhqw9": { "defaultMessage": "立即發布" }, @@ -2890,9 +2934,6 @@ "defaultMessage": "讚賞了", "description": "src/components/Notice/ArticleNotice/ArticleNewAppreciationNotice.tsx" }, - "p6D+Uc": { - "defaultMessage": "請輸入地址" - }, "p9gEZh": { "defaultMessage": "動態最多支持 3 張圖片" }, @@ -3002,12 +3043,18 @@ "defaultMessage": "不可用", "description": "FORBIDDEN_BY_STATE" }, + "rAFb3E": { + "defaultMessage": "Matters 會通過合約交易將 {amount} 發送至你綁定的錢包(Matters 將暫時承擔交易手續費)。" + }, "rDX3h6": { "defaultMessage": "版本簡述" }, "rE7sE3": { "defaultMessage": "CC0 公眾領域貢獻宣告" }, + "rG2xmp": { + "defaultMessage": "提領成功" + }, "rHi+cL": { "defaultMessage": "最多讀者", "description": "src/views/Me/Works/Published/SortTabs.tsx" @@ -3252,9 +3299,6 @@ "defaultMessage": "重置你的登入密碼", "description": "src/components/Dialogs/SetEmailDialog/Content.tsx" }, - "vyG38g": { - "defaultMessage": "錢包地址" - }, "w+6UiO": { "defaultMessage": "新增邀請" }, diff --git a/package-lock.json b/package-lock.json index 1746b77ffd..fd1b6dbb00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "matters-web", - "version": "5.6.2", + "version": "5.7.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "matters-web", - "version": "5.6.2", + "version": "5.7.0", "license": "Apache-2.0", "dependencies": { "@apollo/react-common": "^3.1.3", diff --git a/src/common/enums/contract.ts b/src/common/enums/contract.ts index 10202e5403..084fec14a6 100644 --- a/src/common/enums/contract.ts +++ b/src/common/enums/contract.ts @@ -15,37 +15,43 @@ export const contract = { logbookAddress: '0xcdf8D568EC808de5fCBb35849B5bAFB5d444D4c0' as `0x${string}`, curationAddress: - '0x5edebbdae7B5C79a69AaCF7873796bb1Ec664DB8' as `0x${string}`, + '0x5edebbdae7B5C79a69AaCF7873796bb1Ec664DB8'.toLowerCase() as `0x${string}`, curationBlockNum: '34564355', tokenAddress: - '0xc2132D05D31c914a87C6611C10748AEb04B58e8F' as `0x${string}`, + '0xc2132D05D31c914a87C6611C10748AEb04B58e8F'.toLowerCase() as `0x${string}`, tokenDecimals: 6, } : { logbookAddress: '0x203197e074b7a2f4ff6890815e4657a9c47c68b1' as `0x${string}`, curationAddress: - '0xa219C6722008aa22828B31A13ab9Ba93bB91222c' as `0x${string}`, - curationBlockNum: '28675517' as `0x${string}`, + '0xa219C6722008aa22828B31A13ab9Ba93bB91222c'.toLowerCase() as `0x${string}`, + curationBlockNum: '28675517', tokenAddress: - '0xfe4F5145f6e09952a5ba9e956ED0C25e3Fa4c7F1' as `0x${string}`, + '0xfe4F5145f6e09952a5ba9e956ED0C25e3Fa4c7F1'.toLowerCase() as `0x${string}`, tokenDecimals: 6, }, Optimism: isProd ? { curationAddress: - '0x5edebbdae7B5C79a69AaCF7873796bb1Ec664DB8' as `0x${string}`, - curationBlockNum: '117058632' as `0x${string}`, + '0x5edebbdae7B5C79a69AaCF7873796bb1Ec664DB8'.toLowerCase() as `0x${string}`, + curationBlockNum: '117058632', tokenAddress: - '0x94b008aA00579c1307B0EF2c499aD98a8ce58e58' as `0x${string}`, + '0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'.toLowerCase() as `0x${string}`, tokenDecimals: 6, + curationVaultAddress: + '0x79691206F498CdfAEDD059A48f61835408d81a2F'.toLowerCase() as `0x${string}`, + curationVaultBlockNum: '129071092', } : { curationAddress: - '0x92a117aeA74963Cd0CEdF9C50f99435451a291F7' as `0x${string}`, + '0x92a117aeA74963Cd0CEdF9C50f99435451a291F7'.toLowerCase() as `0x${string}`, curationBlockNum: '8438904', tokenAddress: - '0x5fd84259d66Cd46123540766Be93DFE6D43130D7' as `0x${string}`, + '0x5fd84259d66Cd46123540766Be93DFE6D43130D7'.toLowerCase() as `0x${string}`, tokenDecimals: 6, + curationVaultAddress: + '0xd41be66Bf309Ce5c3949BDe5C8091edc4870c27F'.toLowerCase() as `0x${string}`, + curationVaultBlockNum: '20969176', }, } diff --git a/src/common/enums/events.ts b/src/common/enums/events.ts index f40039c0a2..646341e190 100644 --- a/src/common/enums/events.ts +++ b/src/common/enums/events.ts @@ -42,6 +42,7 @@ export const BYPASS_SCROLL_LOCK = 'bypassScrollLock' export const ENBABLE_SCROLL_LOCK = 'enableScrollLock' export const BYPASS_FOCUS_LOCK = 'bypassFocusLock' export const ENBABLE_FOCUS_LOCK = 'enableFocusLock' +export const OPEN_WITHDRAW_VAULT_USDT_DIALOG = 'openWithdrawVaultUsdtDialog' // Toast export const TOAST_SEND_EMAIL_VERIFICATION = 'toastSendEmailVerification' diff --git a/src/common/enums/test.ts b/src/common/enums/test.ts index 3cb983ce83..04553f177c 100644 --- a/src/common/enums/test.ts +++ b/src/common/enums/test.ts @@ -127,6 +127,7 @@ export enum TEST_ID { NOTICE_TAG_LEAVE_EDITOR = 'notice/tag-leave-editor', NOTICE_PAYMENT_PAYOUT = 'notice/payment-payout', NOTICE_PAYMENT_RECEIVE_DONATION = 'notice/payment-receive-donation', + NOTICE_WITHDREW_LOCKED_TOKENS = 'notice/withdrew-locked-tokens', NOTICE_CIRCLE_NEW_FOLLOWER = 'notice/circle-new-follower', NOTICE_CIRCLE_NEW_SUBSCRIBER = 'notice/circle-new-subscriber', NOTICE_CIRCLE_NEW_UNSUBSCRIBER = 'notice/circle-new-unsubscriber', diff --git a/src/common/enums/url.ts b/src/common/enums/url.ts index b5be7bb1bd..23b072b9c3 100644 --- a/src/common/enums/url.ts +++ b/src/common/enums/url.ts @@ -16,6 +16,13 @@ export const URL_ME_SETTINGS = { OPEN_SET_EMAIL_DIALOG: { key: 'dialog', value: 'set-email' }, } +export const URL_ME_WALLET = { + OPEN_WITHDRAW_VAULT_USDT_DIALOG: { + key: 'dialog', + value: 'withdraw-vault-usdt', + }, +} + export const URL_COLLECTION_DETAIL = { // ?sort=seq:asc,date:dsc SORTER_KEY: 'sort', diff --git a/src/common/utils/abis/curationVault.ts b/src/common/utils/abis/curationVault.ts new file mode 100644 index 0000000000..6ef9baac2d --- /dev/null +++ b/src/common/utils/abis/curationVault.ts @@ -0,0 +1,243 @@ +export const CurationVaultABI = [ + { + inputs: [ + { internalType: 'address', name: 'signer_', type: 'address' }, + { internalType: 'address', name: 'owner_', type: 'address' }, + ], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { inputs: [], name: 'AlreadyWithdrawn', type: 'error' }, + { inputs: [], name: 'Expired', type: 'error' }, + { inputs: [], name: 'InvalidSignature', type: 'error' }, + { inputs: [], name: 'InvalidURI', type: 'error' }, + { inputs: [], name: 'TransferFailed', type: 'error' }, + { inputs: [], name: 'ZeroAddress', type: 'error' }, + { inputs: [], name: 'ZeroAmount', type: 'error' }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'from', type: 'address' }, + { indexed: true, internalType: 'string', name: 'uid', type: 'string' }, + { + indexed: true, + internalType: 'contract IERC20', + name: 'token', + type: 'address', + }, + { indexed: false, internalType: 'string', name: 'uri', type: 'string' }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'Curation', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'from', type: 'address' }, + { indexed: true, internalType: 'string', name: 'uid', type: 'string' }, + { indexed: false, internalType: 'string', name: 'uri', type: 'string' }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'Curation', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'previousOwner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'newOwner', + type: 'address', + }, + ], + name: 'OwnershipTransferred', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'signer', + type: 'address', + }, + ], + name: 'SignerChanged', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + { indexed: true, internalType: 'string', name: 'uid', type: 'string' }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'Withdraw', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + { indexed: true, internalType: 'string', name: 'uid', type: 'string' }, + { + indexed: true, + internalType: 'contract IERC20', + name: 'token', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'Withdraw', + type: 'event', + }, + { + inputs: [ + { internalType: 'string', name: 'uid_', type: 'string' }, + { internalType: 'contract IERC20', name: 'token_', type: 'address' }, + { internalType: 'uint256', name: 'amount_', type: 'uint256' }, + { internalType: 'string', name: 'uri_', type: 'string' }, + ], + name: 'curate', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'string', name: 'uid_', type: 'string' }, + { internalType: 'string', name: 'uri_', type: 'string' }, + ], + name: 'curate', + outputs: [], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { internalType: 'string', name: '', type: 'string' }, + { internalType: 'address', name: '', type: 'address' }, + ], + name: 'erc20Balances', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'string', name: '', type: 'string' }], + name: 'nativeBalances', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'owner', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'renounceOwnership', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'signer_', type: 'address' }], + name: 'setSigner', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'signer', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes4', name: 'interfaceId_', type: 'bytes4' }], + name: 'supportsInterface', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'newOwner', type: 'address' }], + name: 'transferOwnership', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'to_', type: 'address' }, + { internalType: 'string', name: 'uid_', type: 'string' }, + { internalType: 'uint256', name: 'expiredAt_', type: 'uint256' }, + { internalType: 'uint8', name: 'v_', type: 'uint8' }, + { internalType: 'bytes32', name: 'r_', type: 'bytes32' }, + { internalType: 'bytes32', name: 's_', type: 'bytes32' }, + ], + name: 'withdraw', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'to_', type: 'address' }, + { internalType: 'string', name: 'uid_', type: 'string' }, + { internalType: 'contract IERC20', name: 'token_', type: 'address' }, + { internalType: 'uint256', name: 'expiredAt_', type: 'uint256' }, + { internalType: 'uint8', name: 'v_', type: 'uint8' }, + { internalType: 'bytes32', name: 'r_', type: 'bytes32' }, + { internalType: 'bytes32', name: 's_', type: 'bytes32' }, + ], + name: 'withdraw', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'string', name: '', type: 'string' }, + { internalType: 'uint256', name: '', type: 'uint256' }, + ], + name: 'withdrawals', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, +] as const diff --git a/src/common/utils/abis/index.ts b/src/common/utils/abis/index.ts index 567fa47105..6023b3ac6f 100644 --- a/src/common/utils/abis/index.ts +++ b/src/common/utils/abis/index.ts @@ -1,3 +1,4 @@ export * from './billboard' export * from './curation' +export * from './curationVault' export * from './ensPublicResolver' diff --git a/src/common/utils/contract.ts b/src/common/utils/contract.ts new file mode 100644 index 0000000000..24623b4880 --- /dev/null +++ b/src/common/utils/contract.ts @@ -0,0 +1,11 @@ +export const toCurationVaultUID = (userId: string) => { + return `matters:${userId}` +} + +export const parseCurationVaultUID = (uid: string) => { + const match = uid.match(/^matters:(\d+)$/) + if (!match) { + return null + } + return match[1] +} diff --git a/src/common/utils/form/validate.test.ts b/src/common/utils/form/validate.test.ts index c4afbefb90..0cd066783a 100644 --- a/src/common/utils/form/validate.test.ts +++ b/src/common/utils/form/validate.test.ts @@ -37,7 +37,6 @@ import { validateEmail, validatePassword, validatePaymentPassword, - validatePaymentPointer, validatePayoutAmount, validateTagName, validateUserName, @@ -297,18 +296,6 @@ describe('utils/form/validate/validatePaymentPassword', () => { }) }) -describe('utils/form/validate/validatePaymentPointer', () => { - it('should validate payment pointer correctly', () => { - expect(validatePaymentPointer('', intl)).toBe('Required') - expect(validatePaymentPointer('$123456', intl)).toBeUndefined() - - const error = 'The wallet address starts with "$".' - expect(validatePaymentPointer('你好世界🌍', intl)).toBe(error) - expect(validatePaymentPointer('1234', intl)).toBe(error) - expect(validatePaymentPointer('abcd', intl)).toBe(error) - }) -}) - describe('utils/form/validate/validatePayoutAmount', () => { it('should validate payout amount correctly', () => { const min = 100 diff --git a/src/common/utils/form/validate.ts b/src/common/utils/form/validate.ts index 7ac71cc36c..66042e36b7 100644 --- a/src/common/utils/form/validate.ts +++ b/src/common/utils/form/validate.ts @@ -26,7 +26,7 @@ import { ValidEmailOptions, } from '~/common/utils' -import { hasUpperCase, isValidPaymentPointer } from '../validator' +import { hasUpperCase } from '../validator' export const PUNCTUATION_CHINESE = '\u3002\uff1f\uff01\uff0c\u3001\uff1b\uff1a\u201c\u201d\u2018\u2019\uff08\uff09\u300a\u300b\u3008\u3009\u3010\u3011\u300e\u300f\u300c\u300d\ufe43\ufe44\u3014\u3015\u2026\u2014\uff5e\ufe4f\uffe5' @@ -132,20 +132,6 @@ export const validatePaymentPassword = (value: string, intl: IntlShape) => { } } -export const validatePaymentPointer = (value: string, intl: IntlShape) => { - if (!value) { - return intl.formatMessage({ - defaultMessage: 'Required', - id: 'Seanpx', - }) - } else if (!isValidPaymentPointer(value)) { - return intl.formatMessage({ - defaultMessage: 'The wallet address starts with "$".', - id: 'i7cXnf', - }) - } -} - export const validateUserName = (value: string, intl: IntlShape) => { if (value.length > MAX_USER_NAME_LENGTH) { return intl.formatMessage( diff --git a/src/common/utils/index.ts b/src/common/utils/index.ts index 9fe9be7425..def7f2824f 100644 --- a/src/common/utils/index.ts +++ b/src/common/utils/index.ts @@ -3,6 +3,7 @@ export * from './analytics' export * from './audioPlayer' export * from './comment' export * from './connections' +export * from './contract' export * from './cookie' export * from './crypto' export * from './datetime' diff --git a/src/common/utils/validator.test.ts b/src/common/utils/validator.test.ts index 4d915bdf9b..42eb1430ca 100644 --- a/src/common/utils/validator.test.ts +++ b/src/common/utils/validator.test.ts @@ -4,7 +4,6 @@ import { isValidEmail, isValidPassword, isValidPaymentPassword, - isValidPaymentPointer, } from './validator' describe('utils/validator/isValidEmail', () => { @@ -50,15 +49,3 @@ describe('utils/validator/isValidPaymentPassword', () => { expect(isValidPassword('你好世界你你')).toBe(false) }) }) - -describe('utils/validator/isValidPaymentPointer', () => { - it('should return true for valid payment pointers', () => { - expect(isValidPaymentPointer('$example.com')).toBe(true) - expect(isValidPaymentPointer('$www.example.com')).toBe(true) - }) - - it('should return false for invalid payment pointers', () => { - expect(isValidPaymentPointer('example.com')).toBe(false) - expect(isValidPaymentPointer('www.example.com')).toBe(false) - }) -}) diff --git a/src/common/utils/validator.ts b/src/common/utils/validator.ts index 54c75b00c4..c966010870 100644 --- a/src/common/utils/validator.ts +++ b/src/common/utils/validator.ts @@ -49,8 +49,6 @@ export const isValidPaymentPassword = (password: string): boolean => { /** * Validate payment pointer. */ -export const isValidPaymentPointer = (paymentPointer: string): boolean => - paymentPointer.startsWith('$') export const hasUpperCase = (str: string) => str.toLowerCase() !== str diff --git a/src/components/Context/Viewer/index.tsx b/src/components/Context/Viewer/index.tsx index fcf44623b2..8dfa48de64 100644 --- a/src/components/Context/Viewer/index.tsx +++ b/src/components/Context/Viewer/index.tsx @@ -16,7 +16,6 @@ const ViewerFragments = { userName displayName avatar - paymentPointer liker { likerId civicLiker diff --git a/src/components/CurrencyFormatter/index.tsx b/src/components/CurrencyFormatter/index.tsx index 75323f66ee..53db34381b 100644 --- a/src/components/CurrencyFormatter/index.tsx +++ b/src/components/CurrencyFormatter/index.tsx @@ -5,6 +5,8 @@ interface Props { currency: string subValue?: number | string subCurrency?: string + subtitle?: React.ReactNode + weight?: 'normal' | 'medium' } export const CurrencyFormatter: React.FC = ({ @@ -12,15 +14,21 @@ export const CurrencyFormatter: React.FC = ({ currency, subValue, subCurrency, + subtitle, + weight = 'medium', }) => { return ( - + {currency} {value} + {subtitle && {subtitle}} + {subCurrency && ( - + ≈ {subCurrency} {subValue} )} diff --git a/src/components/CurrencyFormatter/styles.module.css b/src/components/CurrencyFormatter/styles.module.css index f888329756..a95638b301 100644 --- a/src/components/CurrencyFormatter/styles.module.css +++ b/src/components/CurrencyFormatter/styles.module.css @@ -6,13 +6,25 @@ & .currency { font-size: var(--text16); - font-weight: var(--font-medium); color: black; + + &.currency-medium { + font-weight: var(--font-medium); + } + + &.currency-normal { + font-weight: var(--font-normal); + } } & .subCurrency { - padding-top: var(--sp8); + padding-top: var(--sp4); font-size: var(--text12); color: var(--color-grey); } + + & .subtitle { + padding-top: var(--sp4); + font-size: var(--text12); + } } diff --git a/src/components/Dialog/Buttons.tsx b/src/components/Dialog/Buttons.tsx index 21119a7130..6044f41081 100644 --- a/src/components/Dialog/Buttons.tsx +++ b/src/components/Dialog/Buttons.tsx @@ -6,12 +6,14 @@ export type DialogTextButtonProps = { text: React.ReactNode color?: 'greyDarker' | 'green' | 'red' | 'black' loading?: boolean + icon?: React.ReactNode } & ButtonProps export const TextButton: React.FC = ({ text, color = 'green', loading, + icon, ...restProps }) => { let buttonProps: ButtonProps = restProps @@ -49,7 +51,11 @@ export const TextButton: React.FC = ({ return ( diff --git a/src/components/Dialogs/AddWalletLoginDialog/Content.tsx b/src/components/Dialogs/AddWalletLoginDialog/Content.tsx index d69441bd65..30d4a3bbc9 100644 --- a/src/components/Dialogs/AddWalletLoginDialog/Content.tsx +++ b/src/components/Dialogs/AddWalletLoginDialog/Content.tsx @@ -6,11 +6,15 @@ import { AuthWalletFeed, Dialog, WalletAuthForm } from '~/components' interface Props { closeDialog: () => void + submitCallback?: () => void } type Step = 'select' | 'connect' -const AddWalletLoginDialogContent: React.FC = ({ closeDialog }) => { +const AddWalletLoginDialogContent: React.FC = ({ + closeDialog, + submitCallback, +}) => { const [step, setStep] = useState('select') const [walletType, setWalletType] = useState('MetaMask') const [hasWalletExist, setHasWalletExist] = useState(false) @@ -63,6 +67,7 @@ const AddWalletLoginDialogContent: React.FC = ({ closeDialog }) => { /> )} + {isConnect && ( = ({ closeDialog }) => { setHasUnavailable(true) setStep('select') }} + submitCallback={submitCallback} /> )} diff --git a/src/components/Dialogs/PaymentPointerDialog/Explainer/index.tsx b/src/components/Dialogs/PaymentPointerDialog/Explainer/index.tsx deleted file mode 100644 index 102c08ea5d..0000000000 --- a/src/components/Dialogs/PaymentPointerDialog/Explainer/index.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import { FormattedMessage } from 'react-intl' - -import styles from './styles.module.css' - -const PaymentPointerExplainer = () => ( - <> -

- - - - ), - link2: ( - - - - ), - link3: ( - - - - ), - link4: ( - - Uphold - - ), - link5: ( - - GateHub - - ), - link6: ( - - - - ), - link7: ( - - Coil - - ), - }} - /> -

- -) - -export default PaymentPointerExplainer diff --git a/src/components/Dialogs/PaymentPointerDialog/Explainer/styles.module.css b/src/components/Dialogs/PaymentPointerDialog/Explainer/styles.module.css deleted file mode 100644 index 54b0bf0522..0000000000 --- a/src/components/Dialogs/PaymentPointerDialog/Explainer/styles.module.css +++ /dev/null @@ -1,5 +0,0 @@ -.content { - & a { - text-decoration: underline; - } -} diff --git a/src/components/Dialogs/PaymentPointerDialog/SetPaymentPointerForm.tsx b/src/components/Dialogs/PaymentPointerDialog/SetPaymentPointerForm.tsx deleted file mode 100644 index 2175cb4b0d..0000000000 --- a/src/components/Dialogs/PaymentPointerDialog/SetPaymentPointerForm.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import { useFormik } from 'formik' -import gql from 'graphql-tag' -import _pickBy from 'lodash/pickBy' -import { useContext, useState } from 'react' -import { FormattedMessage, useIntl } from 'react-intl' - -import { parseFormSubmitErrors, validatePaymentPointer } from '~/common/utils' -import { Dialog, Form, toast, ViewerContext } from '~/components' -import { useMutation } from '~/components/GQL' -import { UpdatePaymentPointerMutation } from '~/gql/graphql' - -import Explainer from './Explainer' - -interface FormProps { - setIsSubmitting: (submitting: boolean) => void - setIsValid: (valid: boolean) => void - closeDialog: () => void - formId?: string -} - -interface FormValues { - paymentPointer: string -} - -const UPDATE_PAYMENT_POINTER = gql` - mutation UpdatePaymentPointer($input: UpdateUserInfoInput!) { - updateUserInfo(input: $input) { - paymentPointer - } - } -` - -const SetPaymentPointerForm: React.FC = ({ - setIsValid, - setIsSubmitting, - closeDialog, - formId = `set-payment-pointer-form`, -}) => { - const intl = useIntl() - const [submitPaymentPointer] = useMutation( - UPDATE_PAYMENT_POINTER - ) - const viewer = useContext(ViewerContext) - - const [defaultPaymentPointer, setDefaultPaymentPointer] = useState( - viewer.paymentPointer || '' - ) - - const { - values, - errors, - touched, - handleBlur, - handleChange, - handleSubmit, - isValid, - } = useFormik({ - initialValues: { - paymentPointer: defaultPaymentPointer, - }, - validateOnBlur: false, - validateOnChange: false, - validate: ({ paymentPointer }) => - _pickBy({ - paymentPointer: validatePaymentPointer(paymentPointer, intl), - }), - onSubmit: async ({ paymentPointer }, { setFieldError }) => { - try { - setIsSubmitting(true) - await submitPaymentPointer({ - variables: { input: { paymentPointer } }, - }) - - toast.success({ - message: ( - - ), - }) - - setDefaultPaymentPointer(paymentPointer) - setIsSubmitting(false) - closeDialog() - } catch (error) { - setIsSubmitting(false) - - const [messages, codes] = parseFormSubmitErrors(error as any) - codes.forEach((code) => { - setFieldError('paymentPointer', intl.formatMessage(messages[code])) - }) - } - }, - }) - - const updateValidity = () => - setIsValid(isValid && values.paymentPointer !== defaultPaymentPointer) - - return ( - - - - -
- { - handleChange(e) - updateValidity() - }} - spacingTop="base" - /> - -
-
- ) -} - -export default SetPaymentPointerForm diff --git a/src/components/Dialogs/PaymentPointerDialog/index.tsx b/src/components/Dialogs/PaymentPointerDialog/index.tsx deleted file mode 100644 index 69de601515..0000000000 --- a/src/components/Dialogs/PaymentPointerDialog/index.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import { useState } from 'react' -import { FormattedMessage } from 'react-intl' - -import { Dialog, useDialogSwitch } from '~/components' - -import SetPaymentPointerForm from './SetPaymentPointerForm' - -interface PaymentPointerProps { - children: ({ openDialog }: { openDialog: () => void }) => React.ReactNode -} - -const BasePaymentPointerDialog: React.FC = ({ - children, -}) => { - const formId = `set-payment-pointer-form` - const [isSubmitting, setIsSubmitting] = useState(false) - const [isValid, setIsValid] = useState(false) - const { show, openDialog, closeDialog } = useDialogSwitch(true) - - const SubmitButton = ( - } - loading={isSubmitting} - /> - ) - - return ( - <> - {children({ openDialog })} - - - - } - closeDialog={closeDialog} - rightBtn={SubmitButton} - /> - - - - - } - color="greyDarker" - onClick={closeDialog} - /> - {SubmitButton} - - } - /> - - - ) -} - -export const PaymentPointerDialog = (props: PaymentPointerProps) => ( - }> - {({ openDialog }) => <>{props.children({ openDialog })}} - -) diff --git a/src/components/Dialogs/WithdrawVaultUSDTDialog/Confirming.tsx b/src/components/Dialogs/WithdrawVaultUSDTDialog/Confirming.tsx new file mode 100644 index 0000000000..28daf94486 --- /dev/null +++ b/src/components/Dialogs/WithdrawVaultUSDTDialog/Confirming.tsx @@ -0,0 +1,208 @@ +import { useMutation, useQuery } from '@apollo/react-hooks' +import gql from 'graphql-tag' +import { useContext, useEffect, useState } from 'react' +import { FormattedMessage } from 'react-intl' + +import { OPEN_WITHDRAW_VAULT_USDT_DIALOG, PATHS } from '~/common/enums' +import { formatAmount, truncate } from '~/common/utils' +import { Dialog, Spinner, toast, useRoute, ViewerContext } from '~/components' +import { + TransactionState, + WithdrawVaultUsdtMutation, + WithdrawVaultUsdtPollingQuery, +} from '~/gql/graphql' + +type ConfirmingProps = { + amount: number + closeDialog: () => void +} + +const WITHDRAW_VAULT_USDT = gql` + mutation WithdrawVaultUSDT { + withdrawLockedTokens { + transaction { + id + state + } + } + } +` + +const WITHDRAW_VAULT_USDT_POLLING = gql` + query WithdrawVaultUSDTPolling($id: ID!) { + viewer { + id + wallet { + transactions(input: { filter: { id: $id } }) { + edges { + node { + id + state + } + } + } + } + } + } +` + +const Confirming: React.FC = ({ amount, closeDialog }) => { + const viewer = useContext(ViewerContext) + const address = viewer.info.ethAddress! + const { router } = useRoute() + + const [withdraw] = useMutation(WITHDRAW_VAULT_USDT) + const [txId, setTxId] = useState(null) + const { startPolling, stopPolling } = useQuery( + WITHDRAW_VAULT_USDT_POLLING, + { + variables: { id: txId }, + errorPolicy: 'none', + fetchPolicy: 'network-only', + skip: typeof window === 'undefined' || !txId, + notifyOnNetworkStatusChange: true, + onCompleted: (data) => { + const tx = data?.viewer?.wallet?.transactions?.edges?.[0]?.node + + if (!tx) { + return + } + + if (tx.state === TransactionState.Succeeded) { + stopPolling() + successToast() + } else if ( + tx.state === TransactionState.Canceled || + tx.state === TransactionState.Failed + ) { + stopPolling() + errorToast() + } + }, + } + ) + + const successToast = () => { + toast.success({ + message: ( + + ), + actions: [ + { + content: ( + + ), + onClick: () => { + router.push(PATHS.ME_WALLET_TRANSACTIONS) + }, + }, + ], + }) + + closeDialog() + } + + const errorToast = () => { + toast.error({ + message: ( + + ), + actions: [ + { + content: ( + + ), + onClick: () => { + window.dispatchEvent( + new CustomEvent(OPEN_WITHDRAW_VAULT_USDT_DIALOG, {}) + ) + }, + }, + ], + }) + + closeDialog() + } + + const onWithdraw = async () => { + try { + const { data } = await withdraw() + const tx = data?.withdrawLockedTokens.transaction + + // If there is a claming tx, start pooling instead + if (tx && tx.state === TransactionState.Pending) { + setTxId(tx.id) + startPolling(3000) + } + // Otherwise, claim is successful + else { + successToast() + } + } catch (error) { + errorToast() + } + } + + useEffect(() => { + onWithdraw() + }, []) + + return ( + <> + + } + /> + + + +

+ + {formatAmount(amount)} USDT + + ), + address: ( + {truncate(address)} + ), + }} + /> +

+
+
+ + } + /> + } + smUpBtns={ + } + icon={} + /> + } + /> + + ) +} + +export default Confirming diff --git a/src/components/Dialogs/WithdrawVaultUSDTDialog/Content.tsx b/src/components/Dialogs/WithdrawVaultUSDTDialog/Content.tsx new file mode 100644 index 0000000000..266a6b7a9a --- /dev/null +++ b/src/components/Dialogs/WithdrawVaultUSDTDialog/Content.tsx @@ -0,0 +1,82 @@ +import dynamic from 'next/dynamic' +import { formatUnits } from 'viem' + +import { contract } from '~/common/enums' +import { SpinnerBlock, useVaultBalanceUSDT } from '~/components' + +import { Step } from './types' + +type WithdrawVaultUSDTDialogContentProps = { + closeDialog: () => void + forward: (step: Step) => void + currStep: Step +} + +const DynamicIntro = dynamic(() => import('./Intro'), { + ssr: false, + loading: () => , +}) + +const DynamicAddWalletLogin = dynamic( + () => import('~/components/Dialogs/AddWalletLoginDialog/Content'), + { ssr: false, loading: () => } +) + +const DynamicConfirming = dynamic(() => import('./Confirming'), { + ssr: false, + loading: () => , +}) + +const WithdrawVaultUSDTDialogContent: React.FC< + WithdrawVaultUSDTDialogContentProps +> = ({ closeDialog, forward, currStep }) => { + const { data: vaultBalanceUSDTData, isLoading: vaultBalanceUSDTLoading } = + useVaultBalanceUSDT() + const vaultBalanceUSDT = parseFloat( + formatUnits( + BigInt(vaultBalanceUSDTData || '0'), + contract.Optimism.tokenDecimals + ) + ) + + const isIntro = currStep === 'intro' + const isConnectWallet = currStep === 'connectWallet' + const isConfirming = currStep === 'confirming' + + return ( + <> + {vaultBalanceUSDTLoading && } + + {isIntro && ( + { + forward('connectWallet') + }} + switchToConfirming={() => { + forward('confirming') + }} + closeDialog={closeDialog} + /> + )} + + {isConnectWallet && ( + { + forward('confirming') + }} + /> + )} + + {isConfirming && ( + + )} + + ) +} + +export default WithdrawVaultUSDTDialogContent diff --git a/src/components/Dialogs/WithdrawVaultUSDTDialog/Intro.tsx b/src/components/Dialogs/WithdrawVaultUSDTDialog/Intro.tsx new file mode 100644 index 0000000000..7a2fab61c9 --- /dev/null +++ b/src/components/Dialogs/WithdrawVaultUSDTDialog/Intro.tsx @@ -0,0 +1,111 @@ +import { useContext } from 'react' +import { FormattedMessage } from 'react-intl' + +import { formatAmount, truncate } from '~/common/utils' +import { Dialog, ViewerContext } from '~/components' + +type IntroProps = { + amount: number + switchToConnectWallet: () => void + switchToConfirming: () => void + closeDialog: () => void +} + +const Intro: React.FC = ({ + amount, + switchToConnectWallet, + switchToConfirming, + closeDialog, +}) => { + const viewer = useContext(ViewerContext) + const address = viewer.info.ethAddress + const isClaimOnly = !!address + + return ( + <> + + ) : ( + + ) + } + /> + + + +

+ {address ? ( + + {formatAmount(amount)} USDT + + ), + address: ( + {truncate(address)} + ), + }} + /> + ) : ( + + {formatAmount(amount)} USDT + + ), + }} + /> + )} +

+
+
+ + + ) : ( + + ) + } + onClick={isClaimOnly ? switchToConfirming : switchToConnectWallet} + /> + } + smUpBtns={ + + ) : ( + + ) + } + onClick={isClaimOnly ? switchToConfirming : switchToConnectWallet} + /> + } + /> + + ) +} + +export default Intro diff --git a/src/components/Dialogs/WithdrawVaultUSDTDialog/index.tsx b/src/components/Dialogs/WithdrawVaultUSDTDialog/index.tsx new file mode 100644 index 0000000000..d65d5179ec --- /dev/null +++ b/src/components/Dialogs/WithdrawVaultUSDTDialog/index.tsx @@ -0,0 +1,60 @@ +import dynamic from 'next/dynamic' +import { useEffect } from 'react' + +import { OPEN_WITHDRAW_VAULT_USDT_DIALOG, URL_ME_WALLET } from '~/common/enums' +import { + Dialog, + SpinnerBlock, + useDialogSwitch, + useEventListener, + useRoute, + useStep, +} from '~/components' + +import { Step } from './types' + +const DynamicContent = dynamic(() => import('./Content'), { + loading: () => , +}) + +const BaseWithdrawVaultUSDTDialog = () => { + const { show, openDialog, closeDialog } = useDialogSwitch(true) + const { currStep, forward } = useStep('intro') + + useEventListener(OPEN_WITHDRAW_VAULT_USDT_DIALOG, openDialog) + + return ( + + + + ) +} + +export const WithdrawVaultUSDTDialog = () => { + const { getQuery } = useRoute() + + const Children = ({ openDialog }: { openDialog: () => void }) => { + useEventListener(OPEN_WITHDRAW_VAULT_USDT_DIALOG, openDialog) + return <> + } + + const shouldOpenDialog = + getQuery(URL_ME_WALLET.OPEN_WITHDRAW_VAULT_USDT_DIALOG.key) === + URL_ME_WALLET.OPEN_WITHDRAW_VAULT_USDT_DIALOG.value + + useEffect(() => { + if (shouldOpenDialog) { + window.dispatchEvent(new CustomEvent(OPEN_WITHDRAW_VAULT_USDT_DIALOG)) + } + }, [shouldOpenDialog]) + + return ( + }> + {({ openDialog }) => } + + ) +} diff --git a/src/components/Dialogs/WithdrawVaultUSDTDialog/types.d.ts b/src/components/Dialogs/WithdrawVaultUSDTDialog/types.d.ts new file mode 100644 index 0000000000..25a92599d1 --- /dev/null +++ b/src/components/Dialogs/WithdrawVaultUSDTDialog/types.d.ts @@ -0,0 +1 @@ +export type Step = 'intro' | 'connectWallet' | 'confirming' diff --git a/src/components/Dialogs/index.tsx b/src/components/Dialogs/index.tsx index 629e2215c0..a59e524f24 100644 --- a/src/components/Dialogs/index.tsx +++ b/src/components/Dialogs/index.tsx @@ -46,7 +46,7 @@ export * from './PayoutDialog' export * from './ResetPaymentPasswordDialog' export * from './SubscribeCircleDialog' export * from './UnsubscribeCircleDialog' +export * from './WithdrawVaultUSDTDialog' // Misc export * from './BillboardDialog' -export * from './PaymentPointerDialog' diff --git a/src/components/Forms/PaymentForm/PayTo/Complete/index.tsx b/src/components/Forms/PaymentForm/PayTo/Complete/index.tsx index eb8fa03e60..3e2f5cfcfc 100644 --- a/src/components/Forms/PaymentForm/PayTo/Complete/index.tsx +++ b/src/components/Forms/PaymentForm/PayTo/Complete/index.tsx @@ -83,7 +83,7 @@ const Complete: React.FC = ({ currency={currency} recipient={recipient} showLikerID={isLikecoin} - showEthAddress={isUSDT} + showEthAddress={isUSDT && !!recipient.info.ethAddress} > <> diff --git a/src/components/Forms/PaymentForm/PayTo/Confirm/index.tsx b/src/components/Forms/PaymentForm/PayTo/Confirm/index.tsx index d55e4757d4..2b0e69c69d 100644 --- a/src/components/Forms/PaymentForm/PayTo/Confirm/index.tsx +++ b/src/components/Forms/PaymentForm/PayTo/Confirm/index.tsx @@ -205,7 +205,9 @@ const Confirm: React.FC = ({ currency={currency} recipient={recipient} showLikerID={currency === CURRENCY.LIKE} - showEthAddress={currency === CURRENCY.USDT} + showEthAddress={ + currency === CURRENCY.USDT && !!recipient.info.ethAddress + } /> {isSubmitting && ( diff --git a/src/components/Forms/PaymentForm/PayTo/SetAmount/index.tsx b/src/components/Forms/PaymentForm/PayTo/SetAmount/index.tsx index ed65c74e11..2966a5f65b 100644 --- a/src/components/Forms/PaymentForm/PayTo/SetAmount/index.tsx +++ b/src/components/Forms/PaymentForm/PayTo/SetAmount/index.tsx @@ -149,13 +149,13 @@ const SetAmount: React.FC = ({ refetch: refetchAllowanceData, isLoading: allowanceLoading, error: allowanceError, - } = useAllowanceUSDT() + } = useAllowanceUSDT(!recipient.info.ethAddress) const { data: approveData, isLoading: approving, write: approveWrite, error: approveError, - } = useApproveUSDT() + } = useApproveUSDT(!recipient.info.ethAddress) const { data: balanceUSDTData, error: balanceUSDTError } = useBalanceUSDT({ address, }) diff --git a/src/components/Forms/PaymentForm/Processing/index.tsx b/src/components/Forms/PaymentForm/Processing/index.tsx index a2078d8e42..406368deb4 100644 --- a/src/components/Forms/PaymentForm/Processing/index.tsx +++ b/src/components/Forms/PaymentForm/Processing/index.tsx @@ -14,7 +14,12 @@ import { PAYMENT_CURRENCY as CURRENCY, SUPPORT_SUCCESS_USDT_VISITOR, } from '~/common/enums' -import { CurationABI } from '~/common/utils' +import { + CurationABI, + CurationVaultABI, + fromGlobalId, + toCurationVaultUID, +} from '~/common/utils' import { Dialog, Icon, @@ -217,11 +222,35 @@ const USDTProcessingForm: React.FC = ({ const [draftTxId, setDraftTxId] = useState() + const useCurationVault = !recipient.info.ethAddress + const normalizedAmount = parseUnits( + amount.toString() as `${number}`, + contract.Optimism.tokenDecimals + ) + const uri = `ipfs://${article?.dataHash}` + + const { + data: vaultData, + error: vaultError, + isError: isVaultError, + write: curateVault, + } = useContractWrite({ + address: contract.Optimism.curationVaultAddress, + abi: CurationVaultABI, + functionName: 'curate', + args: [ + toCurationVaultUID(fromGlobalId(recipient.id).id), + contract.Optimism.tokenAddress, + normalizedAmount, + uri, + ], + }) + const { - data, - error, - isError, - write: curate, + data: curationData, + error: curationError, + isError: isCurationError, + write: curateDirect, } = useContractWrite({ address: contract.Optimism.curationAddress, abi: CurationABI, @@ -229,14 +258,16 @@ const USDTProcessingForm: React.FC = ({ args: [ recipient.info.ethAddress as `0x${string}`, contract.Optimism.tokenAddress, - parseUnits( - amount.toString() as `${number}`, - contract.Optimism.tokenDecimals - ), - `ipfs://${article?.dataHash}`, + normalizedAmount, + uri, ], }) + const data = useCurationVault ? vaultData : curationData + const error = useCurationVault ? vaultError : curationError + const isError = useCurationVault ? isVaultError : isCurationError + const curate = useCurationVault ? curateVault : curateDirect + const payToData = { amount, currency, @@ -327,7 +358,7 @@ const USDTProcessingForm: React.FC = ({ amount={amount} currency={currency} recipient={recipient} - showEthAddress={true} + showEthAddress={!!recipient.info.ethAddress} > {!isError && ( <> diff --git a/src/components/Forms/PaymentForm/SwitchNetwork/index.tsx b/src/components/Forms/PaymentForm/SwitchNetwork/index.tsx index 914747cd2c..2df6549b9c 100644 --- a/src/components/Forms/PaymentForm/SwitchNetwork/index.tsx +++ b/src/components/Forms/PaymentForm/SwitchNetwork/index.tsx @@ -22,7 +22,6 @@ interface SwitchNetworkProps { const SwitchNetwork: React.FC = ({ submitCallback }) => { const { lang } = useContext(LanguageContext) - // TODO: support multiple networks const targetNetork = featureSupportedChains.curation[0] const { isUnsupportedNetwork, switchToTargetNetwork, isSwitchingNetwork } = useTargetNetwork(targetNetork) diff --git a/src/components/Forms/WalletAuthForm/Connect.tsx b/src/components/Forms/WalletAuthForm/Connect.tsx index 72198988e9..41f7297c4e 100644 --- a/src/components/Forms/WalletAuthForm/Connect.tsx +++ b/src/components/Forms/WalletAuthForm/Connect.tsx @@ -253,7 +253,11 @@ const Connect: React.FC = ({ ), }) - !!closeDialog && closeDialog() + if (submitCallback) { + submitCallback() + } else if (closeDialog) { + closeDialog() + } } } catch (error) { const [messages, codes] = parseFormSubmitErrors(error as any) diff --git a/src/components/Head/index.tsx b/src/components/Head/index.tsx index b78b2aad02..95dbb57285 100644 --- a/src/components/Head/index.tsx +++ b/src/components/Head/index.tsx @@ -29,7 +29,6 @@ interface HeadProps { path?: string image?: string | null noSuffix?: boolean - paymentPointer?: string | null jsonLdData?: Record | null availableLanguages?: UserLanguage[] } @@ -224,9 +223,7 @@ export const Head: React.FC = (props) => { key="ld-json-data" /> )} - {props.paymentPointer && ( - - )} + {/* noindex for non-production enviroment */} {!isProdServingCanonical && ( diff --git a/src/components/Hook/index.ts b/src/components/Hook/index.ts index 0c40be308d..1e5f2f1696 100644 --- a/src/components/Hook/index.ts +++ b/src/components/Hook/index.ts @@ -2,7 +2,6 @@ export * from './useBillboard' export * from './useCarousel' export * from './useColorThief' export * from './useCountdown' -export * from './useCuration' export * from './useDialogSwitch' export * from './useDirectImageUpload' export * from './useERC20' diff --git a/src/components/Hook/useCuration.ts b/src/components/Hook/useCuration.ts deleted file mode 100644 index b158cb370c..0000000000 --- a/src/components/Hook/useCuration.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { useContractWrite, usePrepareContractWrite } from 'wagmi' - -import { contract } from '~/common/enums' -import { CurationABI } from '~/common/utils' - -export const useCurate = () => { - const { config } = usePrepareContractWrite({ - address: contract.Optimism.curationAddress, - abi: CurationABI, - functionName: 'curate', - }) - - return useContractWrite(config) -} diff --git a/src/components/Hook/useERC20.ts b/src/components/Hook/useERC20.ts index 28d36ad35d..e183644088 100644 --- a/src/components/Hook/useERC20.ts +++ b/src/components/Hook/useERC20.ts @@ -9,17 +9,28 @@ import { } from 'wagmi' import { contract } from '~/common/enums' -import { featureSupportedChains, MaxApprovedUSDTAmount } from '~/common/utils' +import { + CurationVaultABI, + featureSupportedChains, + fromGlobalId, + MaxApprovedUSDTAmount, + toCurationVaultUID, +} from '~/common/utils' import { ViewerContext } from '~/components' -export const useAllowanceUSDT = () => { +export const useAllowanceUSDT = (useCurationVault: boolean) => { const { address } = useAccount() return useContractRead({ address: contract.Optimism.tokenAddress, abi: erc20ABI, functionName: 'allowance', - args: [address as `0x${string}`, contract.Optimism.curationAddress], + args: [ + address as `0x${string}`, + useCurationVault + ? contract.Optimism.curationVaultAddress + : contract.Optimism.curationAddress, + ], }) } @@ -56,12 +67,33 @@ export const useBalanceEther = ({ }) } -export const useApproveUSDT = () => { +export const useVaultBalanceUSDT = () => { + const viewer = useContext(ViewerContext) + const viewerId = viewer.id + const uid = toCurationVaultUID(fromGlobalId(viewerId).id) + const targetNetwork = featureSupportedChains.curation[0] + + return useContractRead({ + address: contract.Optimism.curationVaultAddress, + abi: CurationVaultABI, + functionName: 'erc20Balances', + args: [uid, contract.Optimism.tokenAddress], + chainId: targetNetwork.id, + cacheTime: 5_000, + }) +} + +export const useApproveUSDT = (useCurationVault: boolean) => { const { config } = usePrepareContractWrite({ address: contract.Optimism.tokenAddress, abi: erc20ABI, functionName: 'approve', - args: [contract.Optimism.curationAddress, MaxApprovedUSDTAmount], + args: [ + useCurationVault + ? contract.Optimism.curationVaultAddress + : contract.Optimism.curationAddress, + MaxApprovedUSDTAmount, + ], }) return useContractWrite(config) diff --git a/src/components/Notice/ArticleArticleNotice/ArticleNewCollectedNotice.tsx b/src/components/Notice/ArticleArticleNotice/ArticleNewCollectedNotice.tsx index 9b862bb2f5..341b5acc6d 100644 --- a/src/components/Notice/ArticleArticleNotice/ArticleNewCollectedNotice.tsx +++ b/src/components/Notice/ArticleArticleNotice/ArticleNewCollectedNotice.tsx @@ -16,10 +16,6 @@ const ArticleNewCollectedNotice = ({ }: { notice: ArticleNewCollectedNoticeFragment }) => { - if (!notice.actors) { - return null - } - return ( { - if (!notice.actors || !notice.circle) { + if (!notice.circle) { return null } @@ -46,7 +46,7 @@ CircleInvitationNotice.fragments = { id ...NoticeDate actors { - ...NoticeActorNameUser + ...NoticeActorAvatarUser } circle: target { id @@ -57,7 +57,7 @@ CircleInvitationNotice.fragments = { ...NoticeCircleCard } } - ${NoticeActorName.fragments.user} + ${NoticeActorAvatar.fragments.user} ${NoticeCircleCard.fragments.circle} ${NoticeDate.fragments.notice} `, diff --git a/src/components/Notice/CircleNotice/CircleNewDiscussionComments.tsx b/src/components/Notice/CircleNotice/CircleNewDiscussionComments.tsx index 63649595a3..a8f3c0821d 100644 --- a/src/components/Notice/CircleNotice/CircleNewDiscussionComments.tsx +++ b/src/components/Notice/CircleNotice/CircleNewDiscussionComments.tsx @@ -24,10 +24,6 @@ const CircleNewDiscussionComments = ({ const viewer = useContext(ViewerContext) const { comments, replies, mentions } = notice - if (!notice.actors) { - return null - } - const isCircleOwner = notice.circle.owner.id === viewer.id const newDiscussionCount = comments?.length const replyCount = replies?.length diff --git a/src/components/Notice/CircleNotice/CircleNewUserNotice.tsx b/src/components/Notice/CircleNotice/CircleNewUserNotice.tsx index c8e4bc7272..b710796393 100644 --- a/src/components/Notice/CircleNotice/CircleNewUserNotice.tsx +++ b/src/components/Notice/CircleNotice/CircleNewUserNotice.tsx @@ -16,10 +16,6 @@ type CircleNewUserNotice = { } const CircleNewUserNotice = ({ notice, userType }: CircleNewUserNotice) => { - if (!notice.actors) { - return null - } - const isNewFollower = userType === 'follower' const isNewSubscriber = userType === 'subscriber' diff --git a/src/components/Notice/CommentNotice/ArticleNewCommentNotice.tsx b/src/components/Notice/CommentNotice/ArticleNewCommentNotice.tsx index 8326efb55f..6c3f0fb783 100644 --- a/src/components/Notice/CommentNotice/ArticleNewCommentNotice.tsx +++ b/src/components/Notice/CommentNotice/ArticleNewCommentNotice.tsx @@ -16,10 +16,6 @@ const ArticleNewCommentNotice = ({ }: { notice: ArticleNewCommentNoticeFragment }) => { - if (!notice.actors) { - return null - } - const commentArticle = notice.comment?.node.__typename === 'Article' ? notice.comment.node diff --git a/src/components/Notice/CommentNotice/CommentLikedNotice.tsx b/src/components/Notice/CommentNotice/CommentLikedNotice.tsx index cf5fc69fc1..3f685c4a71 100644 --- a/src/components/Notice/CommentNotice/CommentLikedNotice.tsx +++ b/src/components/Notice/CommentNotice/CommentLikedNotice.tsx @@ -13,10 +13,6 @@ import NoticeHeadActors from '../NoticeHeadActors' import NoticeMomentTitle from '../NoticeMomentTitle' const CommentLikedNotice = ({ notice }: { notice: CommentNoticeFragment }) => { - if (!notice.actors) { - return null - } - const isMoment = notice.comment.node.__typename === 'Moment' const commentMoment = notice.comment.node.__typename === 'Moment' diff --git a/src/components/Notice/CommentNotice/CommentMentionedYouNotice.tsx b/src/components/Notice/CommentNotice/CommentMentionedYouNotice.tsx index 8a2fb29812..b8cca5394f 100644 --- a/src/components/Notice/CommentNotice/CommentMentionedYouNotice.tsx +++ b/src/components/Notice/CommentNotice/CommentMentionedYouNotice.tsx @@ -19,10 +19,6 @@ const CommentMentionedYouNotice = ({ }: { notice: CommentMentionedYouNoticeFragment }) => { - if (!notice.actors) { - return null - } - const commentArticle = notice.comment?.node.__typename === 'Article' ? notice.comment.node : null const commentCircle = diff --git a/src/components/Notice/CommentNotice/MomentNewCommentNotice.tsx b/src/components/Notice/CommentNotice/MomentNewCommentNotice.tsx index d6232bf265..1e5360658a 100644 --- a/src/components/Notice/CommentNotice/MomentNewCommentNotice.tsx +++ b/src/components/Notice/CommentNotice/MomentNewCommentNotice.tsx @@ -16,10 +16,6 @@ const MomentNewCommentNotice = ({ }: { notice: MomentNewCommentNoticeFragment }) => { - if (!notice.actors) { - return null - } - const commentMoment = notice.comment?.node.__typename === 'Moment' ? notice.comment.node diff --git a/src/components/Notice/NoticeActorAvatar.tsx b/src/components/Notice/NoticeActorAvatar.tsx index 4436090f1c..2db992b15e 100644 --- a/src/components/Notice/NoticeActorAvatar.tsx +++ b/src/components/Notice/NoticeActorAvatar.tsx @@ -1,20 +1,13 @@ import gql from 'graphql-tag' -import { AvatarSize } from '~/components/Avatar' import { UserDigest } from '~/components/UserDigest' import { NoticeActorAvatarUserFragment } from '~/gql/graphql' export const NoticeActorAvatar = ({ user, - size = 32, }: { - user: NoticeActorAvatarUserFragment | null - size?: AvatarSize + user?: NoticeActorAvatarUserFragment }) => { - if (!user) { - return null - } - return } diff --git a/src/components/Notice/NoticeDigest/index.tsx b/src/components/Notice/NoticeDigest/index.tsx index c3c6b4e885..1085e724af 100644 --- a/src/components/Notice/NoticeDigest/index.tsx +++ b/src/components/Notice/NoticeDigest/index.tsx @@ -1,57 +1,21 @@ -import gql from 'graphql-tag' import { ReactElement } from 'react' +import { FormattedMessage } from 'react-intl' import { TEST_ID } from '~/common/enums' -import { - ArticleNewAppreciationNoticeFragment, - ArticleNewCollectedNoticeFragment, - ArticleNewCommentNoticeFragment, - ArticleNewSubscriberNoticeFragment, - CampaignArticleFeaturedNoticeFragment, - CircleInvitationNoticeFragment, - CircleNewBroadcastNoticeFragment, - CircleNewDiscussionCommentsFragment, - CircleNewUserNoticeFragment, - CollectionNewLikeNoticeFragment, - CommentMentionedYouNoticeFragment, - CommentNewReplyNoticeFragment, - MomentLikedNoticeFragment, - MomentMentionedYouNoticeFragment, - MomentNewCommentNoticeFragment, - NoticeActorAvatarUserFragment, - NoticeHeadActorsUserFragment, - PaymentReceivedDonationNoticeFragment, - UserNewFollowerNoticeFragment, -} from '~/gql/graphql' +import { NoticeActorAvatarUserFragment } from '~/gql/graphql' import NoticeActorAvatar from '../NoticeActorAvatar' import NoticeActorsNameAndTitle from '../NoticeActorsNameAndTitle' -import NoticeArticleCard from '../NoticeArticleCard' import NoticeDate from '../NoticeDate' -import NoticeHeadActors from '../NoticeHeadActors' import NoticeMultiActors from '../NoticeMultiActors' import styles from '../styles.module.css' type NoticeDigestProps = { - notice: - | ArticleNewSubscriberNoticeFragment - | ArticleNewAppreciationNoticeFragment - | ArticleNewCollectedNoticeFragment - | ArticleNewCommentNoticeFragment - | CircleInvitationNoticeFragment - | CircleNewBroadcastNoticeFragment - | CircleNewDiscussionCommentsFragment - | CircleNewUserNoticeFragment - | CommentMentionedYouNoticeFragment - | CommentNewReplyNoticeFragment - | PaymentReceivedDonationNoticeFragment - | UserNewFollowerNoticeFragment - | MomentNewCommentNoticeFragment - | MomentLikedNoticeFragment - | MomentMentionedYouNoticeFragment - | CollectionNewLikeNoticeFragment - | CampaignArticleFeaturedNoticeFragment - actors?: (NoticeActorAvatarUserFragment & NoticeHeadActorsUserFragment)[] + notice: { + id: string + actors?: NoticeActorAvatarUserFragment[] | null + createdAt: string + } action: string | ReactElement secondAction?: string | ReactElement title?: string | ReactElement @@ -61,20 +25,16 @@ type NoticeDigestProps = { const NoticeDigest = ({ notice, - actors: extendActors, action, secondAction, title, content, testId, }: NoticeDigestProps) => { - if (!notice.actors) { - return null - } - - let actors = extendActors || notice.actors + const actors = notice.actors || [] const actorsCount = actors.length + const isAnonymous = actorsCount <= 0 const isMultiActors = actorsCount > 1 return ( @@ -83,7 +43,20 @@ const NoticeDigest = ({ {...(testId ? { ['data-test-id']: testId } : {})} >
- + + + {isAnonymous && ( + <> + + +
+ + + +
+ + )} + {!isMultiActors && (
{ +const NoticeMultiActors = ({ actors }: NoticeMultiActorsProps) => { const actorsCount = actors.length const showAll = actorsCount <= 8 @@ -17,7 +17,7 @@ const NoticeMultiActors = ({ actors, size }: NoticeMultiActorsProps) => { return ( <> {actors.map((actor, index) => ( - + ))} ) @@ -26,7 +26,7 @@ const NoticeMultiActors = ({ actors, size }: NoticeMultiActorsProps) => { return ( <> {actors.slice(0, 7).map((actor, index) => ( - + ))} + } + /> - - - + title={ + + } + /> - - - - + title={ + + } + /> + ) } diff --git a/src/views/Circle/Discussion/styles.module.css b/src/views/Circle/Discussion/styles.module.css index bcfcc549be..23923e5691 100644 --- a/src/views/Circle/Discussion/styles.module.css +++ b/src/views/Circle/Discussion/styles.module.css @@ -6,6 +6,10 @@ padding: 0 var(--sp16); margin-top: var(--sp8); + @media (--sm-up) { + padding: 0; + } + & .header { margin-bottom: var(--sp24); } diff --git a/src/views/Circle/Settings/ManageInvitation/Invites/index.tsx b/src/views/Circle/Settings/ManageInvitation/Invites/index.tsx index 17ccf5ee65..c5907ec40e 100644 --- a/src/views/Circle/Settings/ManageInvitation/Invites/index.tsx +++ b/src/views/Circle/Settings/ManageInvitation/Invites/index.tsx @@ -1,7 +1,7 @@ import { useState } from 'react' -import { FormattedMessage } from 'react-intl' +import { useIntl } from 'react-intl' -import { SegmentedTabs } from '~/components' +import { SquareTabs } from '~/components' import AcceptedInvites from './Accepted' import PendingInvites from './Pending' @@ -9,6 +9,7 @@ import PendingInvites from './Pending' type InvitesType = 'accepted' | 'pending' const InvitesFeed: React.FC = () => { + const intl = useIntl() const [type, setType] = useState('pending') const isPending = type === 'pending' @@ -16,29 +17,29 @@ const InvitesFeed: React.FC = () => { return ( <> - - + setType('pending')} selected={isPending} - > - - - - + + setType('accepted')} selected={isAccepted} - > - - - + title={intl.formatMessage({ + defaultMessage: 'Accepted', + id: 'JpS59y', + description: + 'src/views/Circle/Settings/ManageInvitation/Invites/index.tsx', + })} + /> + {isPending && } {isAccepted && } diff --git a/src/views/Me/History/LikesTabs.tsx b/src/views/Me/History/LikesTabs.tsx index 65ffc48529..5b86d81263 100644 --- a/src/views/Me/History/LikesTabs.tsx +++ b/src/views/Me/History/LikesTabs.tsx @@ -1,7 +1,7 @@ import { FormattedMessage } from 'react-intl' import { PATHS } from '~/common/enums' -import { HorizontalRule, SegmentedTabs, useRoute } from '~/components' +import { Button, HorizontalRule, SquareTabs, useRoute } from '~/components' import styles from './styles.module.css' @@ -11,21 +11,25 @@ const LikesTabs: React.FC = () => { return ( <>
- - + - - + title={ + + } + /> - - - - + title={ + + } + /> +
diff --git a/src/views/Me/Settings/Account/Wallet/index.tsx b/src/views/Me/Settings/Account/Wallet/index.tsx index 9ac16a588d..70b54daf45 100644 --- a/src/views/Me/Settings/Account/Wallet/index.tsx +++ b/src/views/Me/Settings/Account/Wallet/index.tsx @@ -8,6 +8,7 @@ import { Icon, RemoveWalletLoginDialog, TableView, + useVaultBalanceUSDT, ViewerContext, } from '~/components' import { SocialAccountType } from '~/gql/graphql' @@ -30,6 +31,9 @@ const Wallet = () => { const canRemoveNonFacebookLogins = +canEmailLogin + +canWalletLogin + nonFacebookSocials.length > 1 + const { data: vaultBalanceUSDT } = useVaultBalanceUSDT() + const hasVaultBalanceUSDT = vaultBalanceUSDT && vaultBalanceUSDT > 0 + return ( {({ openDialog: openAddWalletLoginDialog }) => { @@ -61,10 +65,17 @@ const Wallet = () => { right={ ethAddress ? undefined : ( - + {hasVaultBalanceUSDT ? ( + + ) : ( + + )} ) } diff --git a/src/views/Me/Transactions/index.tsx b/src/views/Me/Transactions/index.tsx index ac9ea922d7..e318456004 100644 --- a/src/views/Me/Transactions/index.tsx +++ b/src/views/Me/Transactions/index.tsx @@ -1,7 +1,7 @@ import { useQuery } from '@apollo/react-hooks' import gql from 'graphql-tag' import { useState } from 'react' -import { FormattedMessage, useIntl } from 'react-intl' +import { useIntl } from 'react-intl' import { analytics, mergeConnections } from '~/common/utils' import { @@ -13,8 +13,8 @@ import { InfiniteScroll, Layout, List, - SegmentedTabs, SpinnerBlock, + SquareTabs, Transaction, } from '~/components' import { MeTransactionsQuery } from '~/gql/graphql' @@ -163,8 +163,9 @@ const Transactions = () => { - {
} > - setPurpose(Purpose.ALL)} - > - - - - + + setPurpose(Purpose.DONATION)} - > - - - - + + setPurpose(Purpose.SUBSCRIPTION)} - > - - - + title={intl.formatMessage({ + defaultMessage: 'Subscriptions', + id: 'T73SwS', + description: 'src/views/Me/Transactions/index.tsx', + })} + /> + diff --git a/src/views/Me/Wallet/Balance/FiatCurrency.tsx b/src/views/Me/Wallet/Balance/FiatCurrency.tsx index f16288b6ed..1361ae0a51 100644 --- a/src/views/Me/Wallet/Balance/FiatCurrency.tsx +++ b/src/views/Me/Wallet/Balance/FiatCurrency.tsx @@ -177,6 +177,7 @@ export const FiatCurrencyBalance: React.FC = ({ balanceHKD * exchangeRate, 2 )} + weight="normal" />
diff --git a/src/views/Me/Wallet/Balance/LikeCoin.tsx b/src/views/Me/Wallet/Balance/LikeCoin.tsx index 8415ffa359..5c6f42eeb0 100644 --- a/src/views/Me/Wallet/Balance/LikeCoin.tsx +++ b/src/views/Me/Wallet/Balance/LikeCoin.tsx @@ -2,6 +2,7 @@ import { useQuery } from '@apollo/react-hooks' import classNames from 'classnames' import gql from 'graphql-tag' import React, { useContext } from 'react' +import { FormattedMessage } from 'react-intl' import { ReactComponent as IconLikeCoin } from '@/public/static/icons/24px/likecoin.svg' import { PATHS } from '~/common/enums' @@ -115,6 +116,7 @@ export const LikeCoinBalance = ({ currency="LIKE" subValue={formatAmount(total * exchangeRate, 2)} subCurrency={currency} + weight="normal" /> ) @@ -125,11 +127,15 @@ export const LikeCoinBalance = ({ diff --git a/src/views/Me/Wallet/Balance/USDT.tsx b/src/views/Me/Wallet/Balance/USDT.tsx index a3c75d33de..83051edb1c 100644 --- a/src/views/Me/Wallet/Balance/USDT.tsx +++ b/src/views/Me/Wallet/Balance/USDT.tsx @@ -1,16 +1,25 @@ import classNames from 'classnames' import { useContext } from 'react' +import { FormattedMessage } from 'react-intl' +import { formatUnits } from 'viem' +import { ReactComponent as IconRight } from '@/public/static/icons/24px/right.svg' import { ReactComponent as IconTether } from '@/public/static/icons/24px/tether.svg' -import { PATHS } from '~/common/enums' +import { + contract, + OPEN_WITHDRAW_VAULT_USDT_DIALOG, + PATHS, +} from '~/common/enums' import { formatAmount } from '~/common/utils' import { Button, CurrencyFormatter, Icon, + Spinner, TextIcon, Translate, useBalanceUSDT, + useVaultBalanceUSDT, ViewerContext, } from '~/components' import { QuoteCurrency } from '~/gql/graphql' @@ -25,15 +34,32 @@ interface USDTBalanceProps { export const USDTBalance = ({ currency, exchangeRate }: USDTBalanceProps) => { const viewer = useContext(ViewerContext) const address = viewer.info.ethAddress - const { data: balanceUSDTData } = useBalanceUSDT({}) + const { data: balanceUSDTData, isLoading: balanceUSDTLoading } = + useBalanceUSDT({}) + const { data: vaultBalanceUSDTData, isLoading: vaultBalanceUSDTLoading } = + useVaultBalanceUSDT() const balanceUSDT = parseFloat(balanceUSDTData?.formatted || '0') + const vaultBalanceUSDT = parseFloat( + formatUnits( + BigInt(vaultBalanceUSDTData || '0'), + contract.Optimism.tokenDecimals + ) + ) + const balance = address ? balanceUSDT : vaultBalanceUSDT + const loading = balanceUSDTLoading || vaultBalanceUSDTLoading + const hasVaultBalance = vaultBalanceUSDT > 0 const classes = classNames({ [styles.assetsItem]: true, assetsItem: true, // global selector for overriding + [styles.clickable]: hasVaultBalance, }) - if (!address) { + const openWithdrawVaultUSDTDialog = () => { + window.dispatchEvent(new CustomEvent(OPEN_WITHDRAW_VAULT_USDT_DIALOG, {})) + } + + if (!address && !vaultBalanceUSDT) { return (
{
@@ -59,7 +89,11 @@ export const USDTBalance = ({ currency, exchangeRate }: USDTBalanceProps) => { } return ( -
+
} size={16} @@ -68,12 +102,43 @@ export const USDTBalance = ({ currency, exchangeRate }: USDTBalanceProps) => { - + {loading ? ( + + ) : ( + } + spacing={8} + placement="left" + > + + ) : ( + + ) + ) : undefined + } + weight="normal" + /> + + )}
) } diff --git a/src/views/Me/Wallet/PaymentPointer/index.tsx b/src/views/Me/Wallet/PaymentPointer/index.tsx deleted file mode 100644 index 42145a4a8a..0000000000 --- a/src/views/Me/Wallet/PaymentPointer/index.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { FormattedMessage } from 'react-intl' - -import { PaymentPointerDialog, TableView } from '~/components' - -const PaymentPointer = () => ( - - {({ openDialog }) => ( - - } - onClick={openDialog} - role="button" - ariaHasPopup="dialog" - /> - )} - -) - -export default PaymentPointer diff --git a/src/views/Me/Wallet/index.tsx b/src/views/Me/Wallet/index.tsx index 25e3247a22..66f1545f39 100644 --- a/src/views/Me/Wallet/index.tsx +++ b/src/views/Me/Wallet/index.tsx @@ -17,6 +17,7 @@ import { TableView, TextIcon, ViewerContext, + WithdrawVaultUSDTDialog, } from '~/components' import EXCHANGE_RATES from '~/components/GQL/queries/exchangeRates' import WALLET_BALANCE from '~/components/GQL/queries/walletBalance' @@ -24,7 +25,6 @@ import { ExchangeRatesQuery, WalletBalanceQuery } from '~/gql/graphql' import { FiatCurrencyBalance, LikeCoinBalance, USDTBalance } from './Balance' import PaymentPassword from './PaymentPassword' -import PaymentPointer from './PaymentPointer' import styles from './styles.module.css' import ViewStripeAccount from './ViewStripeAccount' import ViewStripeCustomerPortal from './ViewStripeCustomerPortal' @@ -96,10 +96,10 @@ const Wallet = () => { @@ -119,24 +119,27 @@ const Wallet = () => { currency={currency} exchangeRate={exchangeRateHKD?.rate || 0} /> - +
{hasPaymentPassword && } + + {hasStripeAccount && } - + + ) } diff --git a/src/views/Search/AggregateResults/Tabs.tsx b/src/views/Search/AggregateResults/Tabs.tsx index 8fdd8a44f8..98711a690a 100644 --- a/src/views/Search/AggregateResults/Tabs.tsx +++ b/src/views/Search/AggregateResults/Tabs.tsx @@ -2,8 +2,6 @@ import { useIntl } from 'react-intl' import { SquareTabs } from '~/components' -import styles from './styles.module.css' - export type TABS = 'article' | 'user' | 'tag' type TabsProps = { @@ -15,33 +13,31 @@ export const Tabs = ({ tab, setTab }: TabsProps) => { const intl = useIntl() return ( -
- - setTab('article')} - title={intl.formatMessage({ - defaultMessage: 'Articles', - id: '3KNMbJ', - })} - /> - setTab('user')} - title={intl.formatMessage({ - defaultMessage: 'Users', - id: 'YDMrKK', - })} - /> - setTab('tag')} - title={intl.formatMessage({ - defaultMessage: 'Tags', - id: '1EYCdR', - })} - /> - -
+ + setTab('article')} + title={intl.formatMessage({ + defaultMessage: 'Articles', + id: '3KNMbJ', + })} + /> + setTab('user')} + title={intl.formatMessage({ + defaultMessage: 'Users', + id: 'YDMrKK', + })} + /> + setTab('tag')} + title={intl.formatMessage({ + defaultMessage: 'Tags', + id: '1EYCdR', + })} + /> + ) } diff --git a/src/views/Search/AggregateResults/styles.module.css b/src/views/Search/AggregateResults/styles.module.css index b664c825a3..2148547f0c 100644 --- a/src/views/Search/AggregateResults/styles.module.css +++ b/src/views/Search/AggregateResults/styles.module.css @@ -31,12 +31,3 @@ .result-item { padding: var(--sp16); } - -.tabs { - padding: 0 var(--sp16); - margin: var(--sp32) 0 var(--sp16); - - @media (--sm-up) { - padding: 0; - } -} diff --git a/src/views/User/UserProfile/FollowingDialog/CirclesFeed/CirclesTabs/index.tsx b/src/views/User/UserProfile/FollowingDialog/CirclesFeed/CirclesTabs/index.tsx index 4f992a359a..d508c20fa6 100644 --- a/src/views/User/UserProfile/FollowingDialog/CirclesFeed/CirclesTabs/index.tsx +++ b/src/views/User/UserProfile/FollowingDialog/CirclesFeed/CirclesTabs/index.tsx @@ -1,4 +1,6 @@ -import { HorizontalRule, SegmentedTabs, Translate } from '~/components' +import { useIntl } from 'react-intl' + +import { HorizontalRule, SquareTabs } from '~/components' import styles from './styles.module.css' @@ -10,30 +12,37 @@ interface CirclesFeedTypeProps { } const CirclesTabs = ({ type, setFeedType }: CirclesFeedTypeProps) => { + const intl = useIntl() const isFollowing = type === 'following' const isSubscribed = type === 'subscribed' return ( - <> -
- - setFeedType('following')} - selected={isFollowing} - > - - - - setFeedType('subscribed')} - selected={isSubscribed} - > - - - - -
- +
+ + setFeedType('following')} + selected={isFollowing} + title={intl.formatMessage({ + defaultMessage: 'Followed', + id: 'nVoVnb', + description: + 'src/views/User/UserProfile/FollowingDialog/CirclesFeed/CirclesTabs/index.tsx', + })} + /> + + setFeedType('subscribed')} + selected={isSubscribed} + title={intl.formatMessage({ + defaultMessage: 'Subscribed', + id: 'mBmmr+', + description: + 'src/views/User/UserProfile/FollowingDialog/CirclesFeed/CirclesTabs/index.tsx', + })} + /> + + +
) } diff --git a/src/views/User/UserProfile/FollowingDialog/CirclesFeed/CirclesTabs/styles.module.css b/src/views/User/UserProfile/FollowingDialog/CirclesFeed/CirclesTabs/styles.module.css index 3a7cf7d27b..3fb1b1d9eb 100644 --- a/src/views/User/UserProfile/FollowingDialog/CirclesFeed/CirclesTabs/styles.module.css +++ b/src/views/User/UserProfile/FollowingDialog/CirclesFeed/CirclesTabs/styles.module.css @@ -1,8 +1,5 @@ .tabs { - padding: var(--sp8) 0; - @media (--sm-up) { - padding: 0; margin: 0 var(--sp20); } }