From 82ae075c28bc80d9a8f2347f40ef0861b03c6b01 Mon Sep 17 00:00:00 2001 From: S2kael Date: Wed, 25 Oct 2023 20:13:30 +0700 Subject: [PATCH 1/9] [Issue-2025] [BuyService] Move to background --- .../src/background/KoniTypes.ts | 6 ++ .../extension-base/src/constants/index.ts | 2 + .../src/koni/background/handlers/Extension.ts | 60 ++++++++++++++ .../src/koni/background/handlers/State.ts | 3 + .../buy-service/constants}/contact.ts | 4 +- .../services/buy-service/constants/index.ts | 5 ++ .../services/buy-service/constants}/token.ts | 72 ++++++++++++---- .../src/services/buy-service/index.ts | 82 +++++++++++++++++++ .../src/services/buy-service/types.ts | 41 ++++++++++ .../src/services/event-service/index.ts | 4 + .../src/services/event-service/types.ts | 4 + packages/extension-base/src/types/buy.ts | 26 ++++++ .../src/{types.ts => types/index.ts} | 2 + .../extension-koni-ui/src/Popup/BuyTokens.tsx | 74 ++++++++--------- .../src/Popup/Home/Tokens/DetailList.tsx | 7 +- packages/extension-koni-ui/src/Popup/Root.tsx | 2 +- .../src/constants/buy/index.ts | 2 - .../src/contexts/DataContext.tsx | 5 +- .../src/stores/feature/Buy.ts | 36 ++++++++ .../extension-koni-ui/src/stores/index.ts | 5 +- .../extension-koni-ui/src/stores/types.ts | 6 ++ .../src/stores/utils/index.ts | 15 ++++ packages/extension-koni/webpack.shared.cjs | 4 +- 23 files changed, 400 insertions(+), 67 deletions(-) rename packages/{extension-koni-ui/src/constants/buy => extension-base/src/services/buy-service/constants}/contact.ts (92%) create mode 100644 packages/extension-base/src/services/buy-service/constants/index.ts rename packages/{extension-koni-ui/src/constants/buy => extension-base/src/services/buy-service/constants}/token.ts (93%) create mode 100644 packages/extension-base/src/services/buy-service/index.ts create mode 100644 packages/extension-base/src/services/buy-service/types.ts create mode 100644 packages/extension-base/src/types/buy.ts rename packages/extension-base/src/{types.ts => types/index.ts} (92%) create mode 100644 packages/extension-koni-ui/src/stores/feature/Buy.ts diff --git a/packages/extension-base/src/background/KoniTypes.ts b/packages/extension-base/src/background/KoniTypes.ts index f31860db65..5052413321 100644 --- a/packages/extension-base/src/background/KoniTypes.ts +++ b/packages/extension-base/src/background/KoniTypes.ts @@ -9,6 +9,7 @@ import { _CHAIN_VALIDATION_ERROR } from '@subwallet/extension-base/services/chai import { _ChainState, _EvmApi, _NetworkUpsertParams, _SubstrateApi, _ValidateCustomAssetRequest, _ValidateCustomAssetResponse, EnableChainParams, EnableMultiChainParams } from '@subwallet/extension-base/services/chain-service/types'; import { SWTransactionResponse, SWTransactionResult } from '@subwallet/extension-base/services/transaction-service/types'; import { WalletConnectNotSupportRequest, WalletConnectSessionRequest } from '@subwallet/extension-base/services/wallet-connect-service/types'; +import { BuyServiceInfo, BuyTokenInfo } from '@subwallet/extension-base/types'; import { InjectedAccount, InjectedAccountWithMeta, MetadataDefBase } from '@subwallet/extension-inject/types'; import { KeyringPair$Json, KeyringPair$Meta } from '@subwallet/keyring/types'; import { KeyringOptions } from '@subwallet/ui-keyring/options/types'; @@ -2380,6 +2381,11 @@ export interface KoniRequestSignatures { 'pri(campaign.banner.subscribe)': [null, CampaignBanner[], CampaignBanner[]]; 'pri(campaign.banner.complete)': [RequestCampaignBannerComplete, boolean]; /* Campaign */ + + /* Buy Service */ + 'pri(buyService.tokens.subscribe)': [null, Record, Record]; + 'pri(buyService.services.subscribe)': [null, Record, Record]; + /* Buy Service */ } export interface ApplicationMetadataType { diff --git a/packages/extension-base/src/constants/index.ts b/packages/extension-base/src/constants/index.ts index 59bb221f20..28b6440bf3 100644 --- a/packages/extension-base/src/constants/index.ts +++ b/packages/extension-base/src/constants/index.ts @@ -27,6 +27,8 @@ export const IGNORE_QR_SIGNER: string[] = []; export const XCM_MIN_AMOUNT_RATIO = 1.2; export const MARKETING_CAMPAIGN_URL = process.env.MARKETING_CAMPAIGN_URL || ''; +export const BUY_TOKEN_URL = process.env.BUY_TOKEN_URL || ''; +export const BUY_SERVICE_CONTACT_URL = process.env.BUY_SERVICE_CONTACT_URL || ''; export * from './staking'; export * from './storage'; diff --git a/packages/extension-base/src/koni/background/handlers/Extension.ts b/packages/extension-base/src/koni/background/handlers/Extension.ts index 9c6a5bb6da..e22966eaca 100644 --- a/packages/extension-base/src/koni/background/handlers/Extension.ts +++ b/packages/extension-base/src/koni/background/handlers/Extension.ts @@ -33,6 +33,7 @@ import { SWTransaction, SWTransactionResponse, SWTransactionResult, TransactionE import { WALLET_CONNECT_EIP155_NAMESPACE } from '@subwallet/extension-base/services/wallet-connect-service/constants'; import { isProposalExpired, isSupportWalletConnectChain, isSupportWalletConnectNamespace } from '@subwallet/extension-base/services/wallet-connect-service/helpers'; import { ResultApproveWalletConnectSession, WalletConnectNotSupportRequest, WalletConnectSessionRequest } from '@subwallet/extension-base/services/wallet-connect-service/types'; +import { BuyServiceInfo, BuyTokenInfo } from '@subwallet/extension-base/types'; import { isSameAddress, reformatAddress, uniqueStringArray } from '@subwallet/extension-base/utils'; import { convertSubjectInfoToAddresses } from '@subwallet/extension-base/utils/address'; import { createTransactionFromRLP, signatureToHex, Transaction as QrTransaction } from '@subwallet/extension-base/utils/eth'; @@ -3866,6 +3867,58 @@ export default class KoniExtension { /* Campaign */ + /* Buy service */ + + private async subscribeBuyTokens (id: string, port: chrome.runtime.Port): Promise> { + const cb = createSubscription<'pri(buyService.tokens.subscribe)'>(id, port); + let ready = false; + + const callback = (rs: Record) => { + if (ready) { + cb(rs); + } + }; + + const subscription = this.#koniState.buyService.subscribeBuyTokens(callback); + + this.createUnsubscriptionHandle(id, subscription.unsubscribe); + + port.onDisconnect.addListener((): void => { + this.cancelSubscription(id); + }); + + await this.#koniState.eventService.waitBuyTokenReady; + ready = true; + + return this.#koniState.buyService.getBuyTokens(); + } + + private async subscribeBuyServices (id: string, port: chrome.runtime.Port): Promise> { + const cb = createSubscription<'pri(buyService.services.subscribe)'>(id, port); + let ready = false; + + const callback = (rs: Record) => { + if (ready) { + cb(rs); + } + }; + + const subscription = this.#koniState.buyService.subscribeBuyServices(callback); + + this.createUnsubscriptionHandle(id, subscription.unsubscribe); + + port.onDisconnect.addListener((): void => { + this.cancelSubscription(id); + }); + + await this.#koniState.eventService.waitBuyServiceReady; + ready = true; + + return this.#koniState.buyService.getBuyServices(); + } + + /* Buy service */ + // -------------------------------------------------------------- // eslint-disable-next-line @typescript-eslint/require-await public async handle (id: string, type: TMessageType, request: RequestTypes[TMessageType], port: chrome.runtime.Port): Promise> { @@ -4341,6 +4394,13 @@ export default class KoniExtension { case 'pri(campaign.banner.complete)': return this.completeCampaignBanner(request as RequestCampaignBannerComplete); /* Campaign */ + + /* Buy service */ + case 'pri(buyService.tokens.subscribe)': + return this.subscribeBuyTokens(id, port); + case 'pri(buyService.services.subscribe)': + return this.subscribeBuyServices(id, port); + /* Buy service */ // Default default: throw new Error(`Unable to handle message of type ${type}`); diff --git a/packages/extension-base/src/koni/background/handlers/State.ts b/packages/extension-base/src/koni/background/handlers/State.ts index af332c157f..e041a89805 100644 --- a/packages/extension-base/src/koni/background/handlers/State.ts +++ b/packages/extension-base/src/koni/background/handlers/State.ts @@ -10,6 +10,7 @@ import { AccountJson, RequestAuthorizeTab, RequestRpcSend, RequestRpcSubscribe, import { ALL_ACCOUNT_KEY, ALL_GENESIS_HASH, MANTA_PAY_BALANCE_INTERVAL } from '@subwallet/extension-base/constants'; import { BalanceService } from '@subwallet/extension-base/services/balance-service'; import { ServiceStatus } from '@subwallet/extension-base/services/base/types'; +import BuyService from '@subwallet/extension-base/services/buy-service'; import CampaignService from '@subwallet/extension-base/services/campaign-service'; import { ChainService } from '@subwallet/extension-base/services/chain-service'; import { _DEFAULT_MANTA_ZK_CHAIN, _MANTA_ZK_CHAIN_GROUP, _PREDEFINED_SINGLE_MODES } from '@subwallet/extension-base/services/chain-service/constants'; @@ -126,6 +127,7 @@ export default class KoniState { readonly subscanService: SubscanService; readonly walletConnectService: WalletConnectService; readonly campaignService: CampaignService; + readonly buyService: BuyService; // Handle the general status of the extension private generalStatus: ServiceStatus = ServiceStatus.INITIALIZING; @@ -151,6 +153,7 @@ export default class KoniState { this.walletConnectService = new WalletConnectService(this, this.requestService); this.migrationService = new MigrationService(this, this.eventService); this.campaignService = new CampaignService(this); + this.buyService = new BuyService(this); this.subscription = new KoniSubscription(this, this.dbService); this.cron = new KoniCron(this, this.subscription, this.dbService); diff --git a/packages/extension-koni-ui/src/constants/buy/contact.ts b/packages/extension-base/src/services/buy-service/constants/contact.ts similarity index 92% rename from packages/extension-koni-ui/src/constants/buy/contact.ts rename to packages/extension-base/src/services/buy-service/constants/contact.ts index cc53438020..947ada6d64 100644 --- a/packages/extension-koni-ui/src/constants/buy/contact.ts +++ b/packages/extension-base/src/services/buy-service/constants/contact.ts @@ -1,7 +1,7 @@ -// Copyright 2019-2022 @subwallet/extension-koni-ui authors & contributors +// Copyright 2019-2022 @subwallet/extension-base authors & contributors // SPDX-License-Identifier: Apache-2.0 -import { BuyServiceInfo, SupportService } from '@subwallet/extension-koni-ui/types'; +import { BuyServiceInfo, SupportService } from '@subwallet/extension-base/types'; export const BUY_SERVICE_CONTACTS: Record = { transak: { diff --git a/packages/extension-base/src/services/buy-service/constants/index.ts b/packages/extension-base/src/services/buy-service/constants/index.ts new file mode 100644 index 0000000000..85a074cd35 --- /dev/null +++ b/packages/extension-base/src/services/buy-service/constants/index.ts @@ -0,0 +1,5 @@ +// Copyright 2019-2022 @subwallet/extension-base authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +export * from './contact'; +export * from './token'; diff --git a/packages/extension-koni-ui/src/constants/buy/token.ts b/packages/extension-base/src/services/buy-service/constants/token.ts similarity index 93% rename from packages/extension-koni-ui/src/constants/buy/token.ts rename to packages/extension-base/src/services/buy-service/constants/token.ts index 6751914a28..e931d28c06 100644 --- a/packages/extension-koni-ui/src/constants/buy/token.ts +++ b/packages/extension-base/src/services/buy-service/constants/token.ts @@ -1,7 +1,7 @@ -// Copyright 2019-2022 @subwallet/extension-koni-ui authors & contributors +// Copyright 2019-2022 @subwallet/extension-base authors & contributors // SPDX-License-Identifier: Apache-2.0 -import { BuyService, BuyTokenInfo, SupportService } from '@subwallet/extension-koni-ui/types'; +import { BuyService, BuyTokenInfo, SupportService } from '@subwallet/extension-base/types'; const DEFAULT_BUY_SERVICE: BuyService = { symbol: '', network: '' }; @@ -99,9 +99,29 @@ export const MAP_PREDEFINED_BUY_TOKEN: Record = { 'banxa' ] }, + 'dockPosMainnet-NATIVE-DOCK': { + serviceInfo: { + ...DEFAULT_SERVICE_INFO, + transak: { + network: 'mainnet', + symbol: 'DOCK' + } + }, + network: 'dockPosMainnet', + slug: 'dockPosMainnet-NATIVE-DOCK', + symbol: 'DOCK', + support: 'SUBSTRATE', + services: [ + 'transak' + ] + }, 'polkadot-NATIVE-DOT': { serviceInfo: { ...DEFAULT_SERVICE_INFO, + transak: { + network: 'mainnet', + symbol: 'DOT' + }, banxa: { network: 'DOT', symbol: 'DOT' @@ -116,6 +136,7 @@ export const MAP_PREDEFINED_BUY_TOKEN: Record = { symbol: 'DOT', support: 'SUBSTRATE', services: [ + 'transak', 'banxa', 'coinbase' ] @@ -233,6 +254,10 @@ export const MAP_PREDEFINED_BUY_TOKEN: Record = { 'moonbeam-NATIVE-GLMR': { serviceInfo: { ...DEFAULT_SERVICE_INFO, + transak: { + network: 'mainnet', + symbol: 'GLMR' + }, banxa: { network: 'GLMR', symbol: 'GLMR' @@ -243,12 +268,17 @@ export const MAP_PREDEFINED_BUY_TOKEN: Record = { symbol: 'GLMR', support: 'ETHEREUM', services: [ + 'transak', 'banxa' ] }, 'kusama-NATIVE-KSM': { serviceInfo: { ...DEFAULT_SERVICE_INFO, + transak: { + network: 'mainnet', + symbol: 'KSM' + }, banxa: { network: 'KSM', symbol: 'KSM' @@ -263,6 +293,7 @@ export const MAP_PREDEFINED_BUY_TOKEN: Record = { symbol: 'KSM', support: 'SUBSTRATE', services: [ + 'transak', 'banxa', 'coinbase' ] @@ -399,22 +430,22 @@ export const MAP_PREDEFINED_BUY_TOKEN: Record = { 'banxa' ] }, - // 'binance-ERC20-BUSD-0xe9e7cea3dedca5984780bafc599bd69add087d56': { - // serviceInfo: { - // ...DEFAULT_SERVICE_INFO, - // transak: { - // network: 'bsc', - // symbol: 'BUSD' - // } - // }, - // network: 'binance', - // slug: 'binance-ERC20-BUSD-0xe9e7cea3dedca5984780bafc599bd69add087d56', - // symbol: 'BUSD', - // support: 'ETHEREUM', - // services: [ - // 'transak' - // ] - // }, + 'binance-ERC20-BUSD-0xe9e7cea3dedca5984780bafc599bd69add087d56': { + serviceInfo: { + ...DEFAULT_SERVICE_INFO, + transak: { + network: 'bsc', + symbol: 'BUSD' + } + }, + network: 'binance', + slug: 'binance-ERC20-BUSD-0xe9e7cea3dedca5984780bafc599bd69add087d56', + symbol: 'BUSD', + support: 'ETHEREUM', + services: [ + 'transak' + ] + }, 'ethereum-ERC20-BUSD-0x4Fabb145d64652a948d72533023f6E7A623C7C53': { serviceInfo: { ...DEFAULT_SERVICE_INFO, @@ -608,6 +639,10 @@ export const MAP_PREDEFINED_BUY_TOKEN: Record = { 'ethereum-ERC20-SAND-0x3845badAde8e6dFF049820680d1F14bD3903a5d0': { serviceInfo: { ...DEFAULT_SERVICE_INFO, + transak: { + network: 'ethereum', + symbol: 'SAND' + }, banxa: { network: 'ETH', symbol: 'SAND' @@ -618,6 +653,7 @@ export const MAP_PREDEFINED_BUY_TOKEN: Record = { symbol: 'SAND', support: 'ETHEREUM', services: [ + 'transak', 'banxa' ] }, diff --git a/packages/extension-base/src/services/buy-service/index.ts b/packages/extension-base/src/services/buy-service/index.ts new file mode 100644 index 0000000000..0a08f4791f --- /dev/null +++ b/packages/extension-base/src/services/buy-service/index.ts @@ -0,0 +1,82 @@ +// Copyright 2019-2022 @subwallet/extension-base authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import { BUY_SERVICE_CONTACT_URL, BUY_TOKEN_URL } from '@subwallet/extension-base/constants'; +import KoniState from '@subwallet/extension-base/koni/background/handlers/State'; +import { BuyServiceInfo, BuyTokenInfo } from '@subwallet/extension-base/types'; +import axios from 'axios'; +import { BehaviorSubject } from 'rxjs'; + +import { BUY_SERVICE_CONTACTS, MAP_PREDEFINED_BUY_TOKEN } from './constants'; + +export default class BuyService { + readonly #state: KoniState; + + private buyTokensSubject = new BehaviorSubject>({}); + private buyServicesSubject = new BehaviorSubject>({}); + + constructor (state: KoniState) { + this.#state = state; + + this.buyTokensSubject.next({}); + this.buyServicesSubject.next({}); + + this.fetchTokens() + .catch((e) => { + console.error('Error on fetch buy tokens', e); + this.#state.eventService.emit('buy.tokens.ready', true); + }); + + this.fetchServices() + .catch((e) => { + console.error('Error on fetch buy services', e); + this.#state.eventService.emit('buy.services.ready', true); + }); + } + + private async fetchTokens () { + const response = await axios.request({ + method: 'GET', + url: BUY_TOKEN_URL + }); + + console.log(response); + + this.buyTokensSubject.next(MAP_PREDEFINED_BUY_TOKEN); + + this.#state.eventService.emit('buy.tokens.ready', true); + } + + private async fetchServices () { + const response = await axios.request({ + method: 'GET', + url: BUY_SERVICE_CONTACT_URL + }); + + console.log(response); + + this.buyServicesSubject.next(BUY_SERVICE_CONTACTS); + + this.#state.eventService.emit('buy.services.ready', true); + } + + public subscribeBuyTokens (callback: (data: Record) => void) { + return this.buyTokensSubject.subscribe({ + next: callback + }); + } + + public getBuyTokens () { + return this.buyTokensSubject.getValue(); + } + + public subscribeBuyServices (callback: (data: Record) => void) { + return this.buyServicesSubject.subscribe({ + next: callback + }); + } + + public getBuyServices () { + return this.buyServicesSubject.getValue(); + } +} diff --git a/packages/extension-base/src/services/buy-service/types.ts b/packages/extension-base/src/services/buy-service/types.ts new file mode 100644 index 0000000000..a8ec91339c --- /dev/null +++ b/packages/extension-base/src/services/buy-service/types.ts @@ -0,0 +1,41 @@ +// Copyright 2019-2022 @subwallet/extension-koni authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import { CampaignAction, CampaignButton } from '@subwallet/extension-base/background/KoniTypes'; + +type Metadata = Record | null; + +interface _BannerData { + id: number; + alt: string; + action: CampaignAction; + metadata: Metadata; + environments: string[]; + position: string[]; + buttons: CampaignButton[]; + media: string; +} + +interface _NotificationData { + id: number; + title: string; + message: string; + repeat: number; + repeatAfter: number; + action: CampaignAction; + metadata: Metadata; + buttons: CampaignButton[]; +} + +interface _CampaignData { + id: number; + name: string; + description: null; + start_time: string; + end_time: string; + condition: Metadata; + banners: _BannerData[]; + notifications: _NotificationData[]; +} + +export type ListCampaignResponse = _CampaignData[] diff --git a/packages/extension-base/src/services/event-service/index.ts b/packages/extension-base/src/services/event-service/index.ts index 56cf521b12..10526cbbb8 100644 --- a/packages/extension-base/src/services/event-service/index.ts +++ b/packages/extension-base/src/services/event-service/index.ts @@ -19,6 +19,8 @@ export class EventService extends EventEmitter { public readonly waitAssetReady: Promise; public readonly waitMigrateReady: Promise; public readonly waitCampaignReady: Promise; + public readonly waitBuyTokenReady: Promise; + public readonly waitBuyServiceReady: Promise; constructor (options: { lazyTime: number } = { lazyTime: 300 }) { super(); @@ -32,6 +34,8 @@ export class EventService extends EventEmitter { this.waitAssetReady = this.generateWaitPromise('asset.ready'); this.waitMigrateReady = this.generateWaitPromise('migration.done'); this.waitCampaignReady = this.generateWaitPromise('campaign.ready'); + this.waitBuyTokenReady = this.generateWaitPromise('buy.tokens.ready'); + this.waitBuyServiceReady = this.generateWaitPromise('buy.services.ready'); } private generateWaitPromise (eventType: T): Promise { diff --git a/packages/extension-base/src/services/event-service/types.ts b/packages/extension-base/src/services/event-service/types.ts index a26d9b8b00..7319e64d85 100644 --- a/packages/extension-base/src/services/event-service/types.ts +++ b/packages/extension-base/src/services/event-service/types.ts @@ -33,6 +33,10 @@ export interface EventRegistry { 'migration.done': [boolean]; 'campaign.ready': [boolean]; + + // Buy token + 'buy.tokens.ready': [boolean]; + 'buy.services.ready': [boolean]; } export type EventType = keyof EventRegistry; diff --git a/packages/extension-base/src/types/buy.ts b/packages/extension-base/src/types/buy.ts new file mode 100644 index 0000000000..6f4532128b --- /dev/null +++ b/packages/extension-base/src/types/buy.ts @@ -0,0 +1,26 @@ +// Copyright 2019-2022 @subwallet/extension-koni-ui authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +export interface BuyService { + network: string; + symbol: string; +} + +export type SupportService = 'transak' | 'banxa' | 'coinbase' | 'moonpay' | 'onramper'; + +export interface BuyTokenInfo { + network: string; + symbol: string; + slug: string; + support: 'ETHEREUM' | 'SUBSTRATE'; + services: Array; + serviceInfo: Record; +} + +export interface BuyServiceInfo { + name: string; + contactUrl: string; + termUrl: string; + policyUrl: string; + url: string; +} diff --git a/packages/extension-base/src/types.ts b/packages/extension-base/src/types/index.ts similarity index 92% rename from packages/extension-base/src/types.ts rename to packages/extension-base/src/types/index.ts index 573409df2f..f6c8db8a34 100644 --- a/packages/extension-base/src/types.ts +++ b/packages/extension-base/src/types/index.ts @@ -10,3 +10,5 @@ export interface Message extends MessageEvent { subscription?: string; } } + +export * from './buy'; diff --git a/packages/extension-koni-ui/src/Popup/BuyTokens.tsx b/packages/extension-koni-ui/src/Popup/BuyTokens.tsx index ede2b43703..503348accc 100644 --- a/packages/extension-koni-ui/src/Popup/BuyTokens.tsx +++ b/packages/extension-koni-ui/src/Popup/BuyTokens.tsx @@ -7,7 +7,6 @@ import { baseServiceItems, Layout, PageWrapper, ServiceItem } from '@subwallet/e import { AccountSelector } from '@subwallet/extension-koni-ui/components/Field/AccountSelector'; import { ServiceSelector } from '@subwallet/extension-koni-ui/components/Field/BuyTokens/ServiceSelector'; import { TokenItemType, TokenSelector } from '@subwallet/extension-koni-ui/components/Field/TokenSelector'; -import { BUY_SERVICE_CONTACTS, LIST_PREDEFINED_BUY_TOKEN, MAP_PREDEFINED_BUY_TOKEN } from '@subwallet/extension-koni-ui/constants'; import { useAssetChecker, useDefaultNavigate, useNotification, useTranslation } from '@subwallet/extension-koni-ui/hooks'; import { RootState } from '@subwallet/extension-koni-ui/stores'; import { AccountType, BuyServiceInfo, CreateBuyOrderFunction, SupportService, ThemeProps } from '@subwallet/extension-koni-ui/types'; @@ -40,22 +39,6 @@ interface LinkUrlProps { content: string; } -const getServiceItems = (tokenSlug: string): ServiceItem[] => { - const buyInfo = MAP_PREDEFINED_BUY_TOKEN[tokenSlug]; - const result: ServiceItem[] = []; - - for (const serviceItem of baseServiceItems) { - const temp: ServiceItem = { - ...serviceItem, - disabled: buyInfo ? !buyInfo.services.includes(serviceItem.key) : true - }; - - result.push(temp); - } - - return result; -}; - const LinkUrl: React.FC = (props: LinkUrlProps) => { if (props.url) { return ( @@ -77,14 +60,6 @@ function Component ({ className }: Props) { const locationState = useLocation().state as BuyTokensParam; const [currentSymbol] = useState(locationState?.symbol); - const fixedTokenKey = useMemo((): string | undefined => { - if (currentSymbol) { - return LIST_PREDEFINED_BUY_TOKEN.filter((value) => value.slug === currentSymbol || value.symbol === currentSymbol)[0]?.slug; - } else { - return undefined; - } - }, [currentSymbol]); - const notify = useNotification(); const { activeModal, inactiveModal } = useContext(ModalContext); @@ -92,8 +67,17 @@ function Component ({ className }: Props) { const { accounts, currentAccount, isAllAccount } = useSelector((state: RootState) => state.accountState); const { chainInfoMap } = useSelector((state: RootState) => state.chainStore); const { walletReference } = useSelector((state: RootState) => state.settings); + const { services, tokens } = useSelector((state: RootState) => state.buyService); const checkAsset = useAssetChecker(); + const fixedTokenKey = useMemo((): string | undefined => { + if (currentSymbol) { + return Object.values(tokens).filter((value) => value.slug === currentSymbol || value.symbol === currentSymbol)[0]?.slug; + } else { + return undefined; + } + }, [currentSymbol, tokens]); + const [currentAddress] = useState(currentAccount?.address); const { t } = useTranslation(); const { goBack } = useDefaultNavigate(); @@ -120,8 +104,24 @@ function Component ({ className }: Props) { const selectedService = Form.useWatch('service', form); const { contactUrl, name: serviceName, policyUrl, termUrl, url } = useMemo((): BuyServiceInfo => { - return BUY_SERVICE_CONTACTS[selectedService] || { name: '', url: '', contactUrl: '', policyUrl: '', termUrl: '' }; - }, [selectedService]); + return services[selectedService] || { name: '', url: '', contactUrl: '', policyUrl: '', termUrl: '' }; + }, [selectedService, services]); + + const getServiceItems = useCallback((tokenSlug: string): ServiceItem[] => { + const buyInfo = tokens[tokenSlug]; + const result: ServiceItem[] = []; + + for (const serviceItem of baseServiceItems) { + const temp: ServiceItem = { + ...serviceItem, + disabled: buyInfo ? !buyInfo.services.includes(serviceItem.key) : true + }; + + result.push(temp); + } + + return result; + }, [tokens]); const onConfirm = useCallback((): Promise => { activeModal(modalId); @@ -162,7 +162,7 @@ function Component ({ className }: Props) { const tokenItems = useMemo(() => { const result: TokenItemType[] = []; - const list = [...LIST_PREDEFINED_BUY_TOKEN]; + const list = [...Object.values(tokens)]; const filtered = currentSymbol ? list.filter((value) => value.slug === currentSymbol || value.symbol === currentSymbol) : list; @@ -189,20 +189,20 @@ function Component ({ className }: Props) { }); return result; - }, [accountType, currentSymbol, ledgerNetwork]); + }, [accountType, currentSymbol, ledgerNetwork, tokens]); - const serviceItems = useMemo(() => getServiceItems(selectedTokenKey), [selectedTokenKey]); + const serviceItems = useMemo(() => getServiceItems(selectedTokenKey), [getServiceItems, selectedTokenKey]); const isSupportBuyTokens = useMemo(() => { if (selectedService && selectedAddress && selectedTokenKey) { - const buyInfo = MAP_PREDEFINED_BUY_TOKEN[selectedTokenKey]; + const buyInfo = tokens[selectedTokenKey]; const accountType = getAccountType(selectedAddress); return buyInfo && buyInfo.support === accountType && buyInfo.services.includes(selectedService) && tokenItems.find((item) => item.slug === selectedTokenKey); } return false; - }, [selectedService, selectedAddress, selectedTokenKey, tokenItems]); + }, [selectedService, selectedAddress, selectedTokenKey, tokens, tokenItems]); const onClickNext = useCallback(() => { setLoading(true); @@ -211,7 +211,7 @@ function Component ({ className }: Props) { let urlPromise: CreateBuyOrderFunction | undefined; - const buyInfo = MAP_PREDEFINED_BUY_TOKEN[tokenKey]; + const buyInfo = tokens[tokenKey]; const { network } = buyInfo; const serviceInfo = buyInfo.serviceInfo[service]; @@ -269,13 +269,13 @@ function Component ({ className }: Props) { } else { setLoading(false); } - }, [form, chainInfoMap, disclaimerAgree, onConfirm, walletReference, notify, t]); + }, [form, tokens, chainInfoMap, disclaimerAgree, onConfirm, walletReference, notify, t]); const filterAccountType = useMemo((): AccountType => { if (currentSymbol) { let result: AccountType = '' as AccountType; - const list = LIST_PREDEFINED_BUY_TOKEN.filter((value) => value.slug === currentSymbol || value.symbol === currentSymbol); + const list = Object.values(tokens).filter((value) => value.slug === currentSymbol || value.symbol === currentSymbol); list.forEach((info) => { if (result) { @@ -293,7 +293,7 @@ function Component ({ className }: Props) { } else { return 'ALL'; } - }, [currentSymbol]); + }, [currentSymbol, tokens]); const accountsFilter = useCallback((account: AccountJson) => { if (isAccountAll(account.address)) { @@ -352,7 +352,7 @@ function Component ({ className }: Props) { form.setFieldValue('service', filtered[0]?.key || ''); } } - }, [selectedTokenKey, form]); + }, [selectedTokenKey, form, getServiceItems]); return ( state.assetRegistry.multiChainAssetMap); const currentAccount = useSelector((state: RootState) => state.accountState.currentAccount); const accounts = useSelector((state: RootState) => state.accountState.accounts); + const { tokens } = useSelector((state: RootState) => state.buyService); const [, setStorage] = useLocalStorage(TRANSFER_TRANSACTION, DEFAULT_TRANSFER_PARAMS); const containerRef = useRef(null); @@ -96,7 +97,7 @@ function Component (): React.ReactElement { const slugs = tokenGroupMap[slug] ? tokenGroupMap[slug] : [slug]; const result: BuyTokenInfo[] = []; - for (const [slug, buyInfo] of Object.entries(MAP_PREDEFINED_BUY_TOKEN)) { + for (const [slug, buyInfo] of Object.entries(tokens)) { if (slugs.includes(slug)) { const supportType = buyInfo.support; @@ -115,7 +116,7 @@ function Component (): React.ReactElement { } return result; - }, [accounts, currentAccount?.address, tokenGroupMap, tokenGroupSlug]); + }, [accounts, currentAccount?.address, tokenGroupMap, tokenGroupSlug, tokens]); const tokenBalanceValue = useMemo(() => { if (tokenGroupSlug) { diff --git a/packages/extension-koni-ui/src/Popup/Root.tsx b/packages/extension-koni-ui/src/Popup/Root.tsx index 16401f7c45..a4cda4819f 100644 --- a/packages/extension-koni-ui/src/Popup/Root.tsx +++ b/packages/extension-koni-ui/src/Popup/Root.tsx @@ -80,7 +80,7 @@ function DefaultRoute ({ children }: { children: React.ReactNode }): React.React const notify = useNotification(); const [rootLoading, setRootLoading] = useState(true); const [dataLoaded, setDataLoaded] = useState(false); - const initDataRef = useRef>(dataContext.awaitStores(['accountState', 'chainStore', 'assetRegistry', 'requestState', 'settings', 'mantaPay', 'campaign'])); + const initDataRef = useRef>(dataContext.awaitStores(['accountState', 'chainStore', 'assetRegistry', 'requestState', 'settings', 'mantaPay', 'campaign', 'buyService'])); const currentPage = useGetCurrentPage(); const firstRender = useRef(true); diff --git a/packages/extension-koni-ui/src/constants/buy/index.ts b/packages/extension-koni-ui/src/constants/buy/index.ts index 9f83183fe0..debe704446 100644 --- a/packages/extension-koni-ui/src/constants/buy/index.ts +++ b/packages/extension-koni-ui/src/constants/buy/index.ts @@ -3,6 +3,4 @@ export * from './banxa'; export * from './coinbase'; -export * from './contact'; export * from './transak'; -export * from './token'; diff --git a/packages/extension-koni-ui/src/contexts/DataContext.tsx b/packages/extension-koni-ui/src/contexts/DataContext.tsx index 5513090d1d..fb31483a1a 100644 --- a/packages/extension-koni-ui/src/contexts/DataContext.tsx +++ b/packages/extension-koni-ui/src/contexts/DataContext.tsx @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { persistor, store, StoreName } from '@subwallet/extension-koni-ui/stores'; -import { getLogoMaps, subscribeAccountsData, subscribeAddressBook, subscribeAssetRegistry, subscribeAssetSettings, subscribeAuthorizeRequests, subscribeAuthUrls, subscribeBalance, subscribeChainInfoMap, subscribeChainStakingMetadata, subscribeChainStateMap, subscribeConfirmationRequests, subscribeConnectWCRequests, subscribeCrowdloan, subscribeKeyringState, subscribeMantaPayConfig, subscribeMantaPaySyncingState, subscribeMetadataRequests, subscribeMultiChainAssetMap, subscribeNftCollections, subscribeNftItems, subscribePrice, subscribeProcessingCampaign, subscribeSigningRequests, subscribeStaking, subscribeStakingNominatorMetadata, subscribeStakingReward, subscribeTransactionRequests, subscribeTxHistory, subscribeUiSettings, subscribeWalletConnectSessions, subscribeWCNotSupportRequests, subscribeXcmRefMap } from '@subwallet/extension-koni-ui/stores/utils'; +import { getLogoMaps, subscribeAccountsData, subscribeAddressBook, subscribeAssetRegistry, subscribeAssetSettings, subscribeAuthorizeRequests, subscribeAuthUrls, subscribeBalance, subscribeBuyServices, subscribeBuyTokens, subscribeChainInfoMap, subscribeChainStakingMetadata, subscribeChainStateMap, subscribeConfirmationRequests, subscribeConnectWCRequests, subscribeCrowdloan, subscribeKeyringState, subscribeMantaPayConfig, subscribeMantaPaySyncingState, subscribeMetadataRequests, subscribeMultiChainAssetMap, subscribeNftCollections, subscribeNftItems, subscribePrice, subscribeProcessingCampaign, subscribeSigningRequests, subscribeStaking, subscribeStakingNominatorMetadata, subscribeStakingReward, subscribeTransactionRequests, subscribeTxHistory, subscribeUiSettings, subscribeWalletConnectSessions, subscribeWCNotSupportRequests, subscribeXcmRefMap } from '@subwallet/extension-koni-ui/stores/utils'; import Bowser from 'bowser'; import React from 'react'; import { Provider } from 'react-redux'; @@ -205,6 +205,9 @@ export const DataContextProvider = ({ children }: DataContextProviderProps) => { _DataContext.addHandler({ ...subscribeProcessingCampaign, name: 'subscribeProcessingCampaign', relatedStores: ['campaign'], isStartImmediately: true }); + _DataContext.addHandler({ ...subscribeBuyTokens, name: 'subscribeBuyTokens', relatedStores: ['buyService'], isStartImmediately: true }); + _DataContext.addHandler({ ...subscribeBuyServices, name: 'subscribeBuyServices', relatedStores: ['buyService'], isStartImmediately: true }); + // Settings _DataContext.addHandler({ ...subscribeUiSettings, name: 'subscribeUiSettings', relatedStores: ['settings'], isStartImmediately: true }); _DataContext.addHandler({ ...getLogoMaps, name: 'getLogoMaps', relatedStores: ['settings'], isStartImmediately: true }); diff --git a/packages/extension-koni-ui/src/stores/feature/Buy.ts b/packages/extension-koni-ui/src/stores/feature/Buy.ts new file mode 100644 index 0000000000..b4f976f34a --- /dev/null +++ b/packages/extension-koni-ui/src/stores/feature/Buy.ts @@ -0,0 +1,36 @@ +// Copyright 2019-2022 @polkadot/extension-ui authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import { createSlice, PayloadAction } from '@reduxjs/toolkit/dist'; +import { BuyServiceInfo, BuyTokenInfo } from '@subwallet/extension-base/types'; +import { BuyServiceStore, ReduxStatus } from '@subwallet/extension-koni-ui/stores/types'; + +const initialState: BuyServiceStore = { + tokens: {}, + services: {}, + reduxStatus: ReduxStatus.INIT +}; + +const buyServiceSlice = createSlice({ + initialState, + name: 'buyService', + reducers: { + updateBuyTokens (state, action: PayloadAction>): BuyServiceStore { + return { + ...state, + tokens: action.payload, + reduxStatus: ReduxStatus.READY + }; + }, + updateBuyServices (state, action: PayloadAction>): BuyServiceStore { + return { + ...state, + services: action.payload, + reduxStatus: ReduxStatus.READY + }; + } + } +}); + +export const { updateBuyServices, updateBuyTokens } = buyServiceSlice.actions; +export default buyServiceSlice.reducer; diff --git a/packages/extension-koni-ui/src/stores/index.ts b/packages/extension-koni-ui/src/stores/index.ts index c592ae0acf..dc4ee0fcad 100644 --- a/packages/extension-koni-ui/src/stores/index.ts +++ b/packages/extension-koni-ui/src/stores/index.ts @@ -11,6 +11,7 @@ import SettingsReducer from './base/Settings'; import UIViewStateReducer from './base/UIViewState'; import BalanceReducer from './feature/Balance'; import BondingReducer from './feature/Bonding'; +import BuyServiceReducer from './feature/Buy'; import CampaignReducer from './feature/Campaign'; import AssetRegistryReducer from './feature/common/AssetRegistry'; import ChainStoreReducer from './feature/common/ChainStore'; @@ -30,7 +31,8 @@ const persistConfig = { 'settings', 'uiViewState', 'staking', - 'campaign' + 'campaign', + 'buyService' ] }; @@ -45,6 +47,7 @@ const rootReducers = combineReducers({ bonding: BondingReducer, mantaPay: MantaPayReducer, campaign: CampaignReducer, + buyService: BuyServiceReducer, // common chainStore: ChainStoreReducer, diff --git a/packages/extension-koni-ui/src/stores/types.ts b/packages/extension-koni-ui/src/stores/types.ts index abc2bff165..658bbb9a22 100644 --- a/packages/extension-koni-ui/src/stores/types.ts +++ b/packages/extension-koni-ui/src/stores/types.ts @@ -8,6 +8,7 @@ import { AccountJson, AccountsContext, AuthorizeRequest, MetadataRequest, Signin import { _ChainState } from '@subwallet/extension-base/services/chain-service/types'; import { SWTransactionResult } from '@subwallet/extension-base/services/transaction-service/types'; import { WalletConnectNotSupportRequest, WalletConnectSessionRequest } from '@subwallet/extension-base/services/wallet-connect-service/types'; +import { BuyServiceInfo, BuyTokenInfo } from '@subwallet/extension-base/types'; import { SessionTypes } from '@walletconnect/types'; import { SettingsStruct } from '@polkadot/ui-settings/types'; @@ -127,6 +128,11 @@ export interface CampaignStore extends BaseReduxStore { banners: CampaignBanner[] } +export interface BuyServiceStore extends BaseReduxStore { + tokens: Record; + services: Record; +} + export type PriceStore = PriceJson export interface CrowdloanStore extends BaseReduxStore { diff --git a/packages/extension-koni-ui/src/stores/utils/index.ts b/packages/extension-koni-ui/src/stores/utils/index.ts index 3dc6544734..e20b5a156a 100644 --- a/packages/extension-koni-ui/src/stores/utils/index.ts +++ b/packages/extension-koni-ui/src/stores/utils/index.ts @@ -8,6 +8,7 @@ import { AccountJson, AccountsContext, AuthorizeRequest, ConfirmationRequestBase import { _ChainState } from '@subwallet/extension-base/services/chain-service/types'; import { SWTransactionResult } from '@subwallet/extension-base/services/transaction-service/types'; import { WalletConnectNotSupportRequest, WalletConnectSessionRequest } from '@subwallet/extension-base/services/wallet-connect-service/types'; +import { BuyServiceInfo, BuyTokenInfo } from '@subwallet/extension-base/types'; import { canDerive } from '@subwallet/extension-base/utils'; import { lazySendMessage, lazySubscribeMessage } from '@subwallet/extension-koni-ui/messaging'; import { store } from '@subwallet/extension-koni-ui/stores'; @@ -300,3 +301,17 @@ export const updateBanner = (data: CampaignBanner[]) => { export const subscribeProcessingCampaign = lazySubscribeMessage('pri(campaign.banner.subscribe)', null, updateBanner, updateBanner); /* Campaign */ + +/* Buy service */ +export const updateBuyTokens = (data: Record) => { + store.dispatch({ type: 'buyService/updateBuyTokens', payload: data }); +}; + +export const subscribeBuyTokens = lazySubscribeMessage('pri(buyService.tokens.subscribe)', null, updateBuyTokens, updateBuyTokens); + +export const updateBuyServices = (data: Record) => { + store.dispatch({ type: 'buyService/updateBuyServices', payload: data }); +}; + +export const subscribeBuyServices = lazySubscribeMessage('pri(buyService.services.subscribe)', null, updateBuyServices, updateBuyServices); +/* Buy service */ diff --git a/packages/extension-koni/webpack.shared.cjs b/packages/extension-koni/webpack.shared.cjs index 208ad73483..25d50d6fce 100644 --- a/packages/extension-koni/webpack.shared.cjs +++ b/packages/extension-koni/webpack.shared.cjs @@ -43,8 +43,8 @@ const _additionalEnv = { TRANSAK_API_KEY: JSON.stringify(process.env.TRANSAK_API_KEY), COINBASE_PAY_ID: JSON.stringify(process.env.COINBASE_PAY_ID), MARKETING_CAMPAIGN_URL: JSON.stringify(process.env.MARKETING_CAMPAIGN_URL), - TRANSAK_TEST_MODE: mode === 'production' ? JSON.stringify(false) : JSON.stringify(true), - BANXA_TEST_MODE: mode === 'production' ? JSON.stringify(false) : JSON.stringify(true) + TRANSAK_TEST_MODE: JSON.stringify(false), + BANXA_TEST_MODE: JSON.stringify(false) }; const additionalEnvDict = { From 2a7e7f6f0c7115eeb833714ca3b0bd0f21bc4ada Mon Sep 17 00:00:00 2001 From: S2kael Date: Thu, 26 Oct 2023 15:38:25 +0700 Subject: [PATCH 2/9] [Issue-2025] [BuyService] Fetch online --- .env.example | 2 + .github/workflows/push-koni-dev.yml | 2 + .github/workflows/push-master.yml | 2 + .../services/buy-service/constants/contact.ts | 43 - .../services/buy-service/constants/index.ts | 1 - .../services/buy-service/constants/token.ts | 827 +----------------- .../src/services/buy-service/index.ts | 55 +- .../src/services/buy-service/types.ts | 46 +- packages/extension-koni/webpack.shared.cjs | 2 + 9 files changed, 74 insertions(+), 906 deletions(-) delete mode 100644 packages/extension-base/src/services/buy-service/constants/contact.ts diff --git a/.env.example b/.env.example index 6522672143..be71b269e7 100644 --- a/.env.example +++ b/.env.example @@ -3,3 +3,5 @@ COINBASE_PAY_ID=1dbd2a0b94 BANXA_SANDBOX_API_KEY=subwallet@test24052023@/*436*/ BANXA_SANBOX_API_SECRET=JV5TjrKzl9gO8t8GK4oGhvDEnxAVJIc0 MARKETING_CAMPAIGN_URL=https://static-data.subwallet.app/marketing-campaigns/list.json +BUY_TOKEN_URL: https://static-data.subwallet.app/buy-token-configs/list.json +BUY_SERVICE_CONTACT_URL: https://static-data.subwallet.app/buy-service-infos/list.json diff --git a/.github/workflows/push-koni-dev.yml b/.github/workflows/push-koni-dev.yml index f5bbd781d7..6f6172603a 100644 --- a/.github/workflows/push-koni-dev.yml +++ b/.github/workflows/push-koni-dev.yml @@ -45,6 +45,8 @@ jobs: TRANSAK_API_KEY: ${{ secrets.TRANSAK_API_KEY }} COINBASE_PAY_ID: ${{ secrets.COINBASE_PAY_ID }} MARKETING_CAMPAIGN_URL: https://static-data.subwallet.app/marketing-campaigns/preview.json + BUY_TOKEN_URL: https://static-data.subwallet.app/buy-token-configs/preview.json + BUY_SERVICE_CONTACT_URL: https://static-data.subwallet.app/buy-service-infos/preview.json GH_RELEASE_FILES: master-build.zip,master-src.zip COMMIT_MESSAGE: ${{ github.event.head_commit.message }} REF_NAME: ${{ github.ref_name }} diff --git a/.github/workflows/push-master.yml b/.github/workflows/push-master.yml index 8b8f1ff72f..e94aa66e28 100644 --- a/.github/workflows/push-master.yml +++ b/.github/workflows/push-master.yml @@ -28,6 +28,8 @@ jobs: TRANSAK_API_KEY: ${{ secrets.TRANSAK_API_KEY }} COINBASE_PAY_ID: ${{ secrets.COINBASE_PAY_ID }} MARKETING_CAMPAIGN_URL: https://static-data.subwallet.app/marketing-campaigns/list.json + BUY_TOKEN_URL: https://static-data.subwallet.app/buy-token-configs/list.json + BUY_SERVICE_CONTACT_URL: https://static-data.subwallet.app/buy-service-infos/list.json run: | yarn install --immutable | grep -v 'YN0013' yarn ${{ matrix.step }} diff --git a/packages/extension-base/src/services/buy-service/constants/contact.ts b/packages/extension-base/src/services/buy-service/constants/contact.ts deleted file mode 100644 index 947ada6d64..0000000000 --- a/packages/extension-base/src/services/buy-service/constants/contact.ts +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2019-2022 @subwallet/extension-base authors & contributors -// SPDX-License-Identifier: Apache-2.0 - -import { BuyServiceInfo, SupportService } from '@subwallet/extension-base/types'; - -export const BUY_SERVICE_CONTACTS: Record = { - transak: { - contactUrl: 'https://support.transak.com/', - name: 'Transak', - policyUrl: 'https://transak.com/privacy-policy', - url: 'https://transak.com/', - termUrl: 'https://transak.com/terms-of-service' - }, - banxa: { - contactUrl: 'http://support.banxa.com/', - name: 'Banxa', - policyUrl: 'https://banxa.com/wp-content/uploads/2023/07/Privacy-and-Cookies-Policy-19-June-2023.pdf', - url: 'https://banxa.com/', - termUrl: 'https://banxa.com/wp-content/uploads/2023/07/Customer-Terms-and-Conditions-19-June-2023.pdf' - }, - // TODO: Change text and url - coinbase: { - contactUrl: 'https://help.coinbase.com/en/contact-us', - name: 'Coinbase', - policyUrl: 'https://coinbase.com/legal/privacy', - url: 'https://coinbase.com/', - termUrl: 'https://coinbase.com/legal/user_agreement/united_states' - }, - moonpay: { - contactUrl: 'https://support.moonpay.com/', - name: 'MoonPay', - policyUrl: '', - url: '', - termUrl: '' - }, - onramper: { - contactUrl: '', - name: '', - policyUrl: '', - url: '', - termUrl: '' - } -}; diff --git a/packages/extension-base/src/services/buy-service/constants/index.ts b/packages/extension-base/src/services/buy-service/constants/index.ts index 85a074cd35..0326aed802 100644 --- a/packages/extension-base/src/services/buy-service/constants/index.ts +++ b/packages/extension-base/src/services/buy-service/constants/index.ts @@ -1,5 +1,4 @@ // Copyright 2019-2022 @subwallet/extension-base authors & contributors // SPDX-License-Identifier: Apache-2.0 -export * from './contact'; export * from './token'; diff --git a/packages/extension-base/src/services/buy-service/constants/token.ts b/packages/extension-base/src/services/buy-service/constants/token.ts index e931d28c06..41cea6a2c1 100644 --- a/packages/extension-base/src/services/buy-service/constants/token.ts +++ b/packages/extension-base/src/services/buy-service/constants/token.ts @@ -1,837 +1,14 @@ // Copyright 2019-2022 @subwallet/extension-base authors & contributors // SPDX-License-Identifier: Apache-2.0 -import { BuyService, BuyTokenInfo, SupportService } from '@subwallet/extension-base/types'; +import { BuyService, SupportService } from '@subwallet/extension-base/types'; const DEFAULT_BUY_SERVICE: BuyService = { symbol: '', network: '' }; -const DEFAULT_SERVICE_INFO: Record = { +export const DEFAULT_SERVICE_INFO: Record = { transak: { ...DEFAULT_BUY_SERVICE }, banxa: { ...DEFAULT_BUY_SERVICE }, coinbase: { ...DEFAULT_BUY_SERVICE }, onramper: { ...DEFAULT_BUY_SERVICE }, moonpay: { ...DEFAULT_BUY_SERVICE } }; - -export const MAP_PREDEFINED_BUY_TOKEN: Record = { - 'astar-NATIVE-ASTR': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'astar', - symbol: 'ASTR' - } - }, - network: 'astar', - slug: 'astar-NATIVE-ASTR', - symbol: 'ASTR', - support: 'SUBSTRATE', - services: [ - 'transak' - ] - }, - 'avalanche_c-NATIVE-AVAX': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'avaxcchain', - symbol: 'AVAX' - }, - coinbase: { - network: 'avalanche-c-chain', - symbol: 'AVAX' - } - }, - network: 'avalanche_c', - slug: 'avalanche_c-NATIVE-AVAX', - symbol: 'AVAX', - support: 'ETHEREUM', - services: [ - 'transak', - 'coinbase' - ] - }, - 'aleph-NATIVE-AZERO': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'alephzero', - symbol: 'AZERO' - } - }, - network: 'aleph', - slug: 'aleph-NATIVE-AZERO', - symbol: 'AZERO', - support: 'SUBSTRATE', - services: [ - 'transak' - ] - }, - 'binance-NATIVE-BNB': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'bsc', - symbol: 'BNB' - } - }, - network: 'binance', - slug: 'binance-NATIVE-BNB', - symbol: 'BNB', - support: 'ETHEREUM', - services: [ - 'transak' - ] - }, - 'ternoa-NATIVE-CAPS': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - banxa: { - network: 'TERNOA', - symbol: 'CAPS' - } - }, - network: 'ternoa', - slug: 'ternoa-NATIVE-CAPS', - symbol: 'CAPS', - support: 'SUBSTRATE', - services: [ - 'banxa' - ] - }, - 'dockPosMainnet-NATIVE-DOCK': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'mainnet', - symbol: 'DOCK' - } - }, - network: 'dockPosMainnet', - slug: 'dockPosMainnet-NATIVE-DOCK', - symbol: 'DOCK', - support: 'SUBSTRATE', - services: [ - 'transak' - ] - }, - 'polkadot-NATIVE-DOT': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'mainnet', - symbol: 'DOT' - }, - banxa: { - network: 'DOT', - symbol: 'DOT' - }, - coinbase: { - network: 'polkadot', - symbol: 'DOT' - } - }, - network: 'polkadot', - slug: 'polkadot-NATIVE-DOT', - symbol: 'DOT', - support: 'SUBSTRATE', - services: [ - 'transak', - 'banxa', - 'coinbase' - ] - }, - 'arbitrum_one-NATIVE-ETH': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'arbitrum', - symbol: 'ETH' - }, - coinbase: { - network: 'arbitrum', - symbol: 'ETH' - } - }, - network: 'arbitrum_one', - slug: 'arbitrum_one-NATIVE-ETH', - symbol: 'ETH', - support: 'ETHEREUM', - services: [ - 'transak', - 'coinbase' - ] - }, - 'base_mainnet-NATIVE-ETH': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'base', - symbol: 'ETH' - }, - coinbase: { - network: 'base', - symbol: 'ETH' - } - }, - network: 'base_mainnet', - slug: 'base_mainnet-NATIVE-ETH', - symbol: 'ETH', - support: 'ETHEREUM', - services: [ - 'transak', - 'coinbase' - ] - }, - 'ethereum-NATIVE-ETH': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'ethereum', - symbol: 'ETH' - }, - banxa: { - network: 'ETH', - symbol: 'ETH' - }, - coinbase: { - network: 'ethereum', - symbol: 'ETH' - } - }, - network: 'ethereum', - slug: 'ethereum-NATIVE-ETH', - symbol: 'ETH', - support: 'ETHEREUM', - services: [ - 'transak', - 'banxa', - 'coinbase' - ] - }, - 'optimism-NATIVE-ETH': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'optimism', - symbol: 'ETH' - }, - coinbase: { - network: 'optimism', - symbol: 'ETH' - } - }, - network: 'optimism', - slug: 'optimism-NATIVE-ETH', - symbol: 'ETH', - support: 'ETHEREUM', - services: [ - 'transak', - 'coinbase' - ] - }, - 'fantom-NATIVE-FTM': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'fantom', - symbol: 'FTM' - }, - banxa: { - network: 'FTM', - symbol: 'FTM' - } - }, - network: 'fantom', - slug: 'fantom-NATIVE-FTM', - symbol: 'FTM', - support: 'ETHEREUM', - services: [ - 'transak', - 'banxa' - ] - }, - 'moonbeam-NATIVE-GLMR': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'mainnet', - symbol: 'GLMR' - }, - banxa: { - network: 'GLMR', - symbol: 'GLMR' - } - }, - network: 'moonbeam', - slug: 'moonbeam-NATIVE-GLMR', - symbol: 'GLMR', - support: 'ETHEREUM', - services: [ - 'transak', - 'banxa' - ] - }, - 'kusama-NATIVE-KSM': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'mainnet', - symbol: 'KSM' - }, - banxa: { - network: 'KSM', - symbol: 'KSM' - }, - coinbase: { - network: 'kusama', - symbol: 'KSM' - } - }, - network: 'kusama', - slug: 'kusama-NATIVE-KSM', - symbol: 'KSM', - support: 'SUBSTRATE', - services: [ - 'transak', - 'banxa', - 'coinbase' - ] - }, - 'polygon-NATIVE-MATIC': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'polygon', - symbol: 'MATIC' - }, - banxa: { - network: 'MATIC', - symbol: 'MATIC' - }, - coinbase: { - network: 'polygon', - symbol: 'MATIC' - } - }, - network: 'polygon', - slug: 'polygon-NATIVE-MATIC', - symbol: 'MATIC', - support: 'ETHEREUM', - services: [ - 'transak', - 'banxa', - 'coinbase' - ] - }, - 'moonriver-NATIVE-MOVR': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'moonriver', - symbol: 'MOVR' - } - }, - network: 'moonriver', - slug: 'moonriver-NATIVE-MOVR', - symbol: 'MOVR', - support: 'ETHEREUM', - services: [ - 'transak' - ] - }, - 'pioneer-NATIVE-NEER': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'pioneer', - symbol: 'NEER' - } - }, - network: 'pioneer', - slug: 'pioneer-NATIVE-NEER', - symbol: 'NEER', - support: 'SUBSTRATE', - services: [ - 'transak' - ] - }, - 'ethereum-ERC20-1INCH-0x111111111117dC0aa78b770fA6A738034120C302': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'ethereum', - symbol: '1INCH' - } - }, - network: 'ethereum', - slug: 'ethereum-ERC20-1INCH-0x111111111117dC0aa78b770fA6A738034120C302', - symbol: '1INCH', - support: 'ETHEREUM', - services: [ - 'transak' - ] - }, - 'ethereum-ERC20-APE-0x4d224452801ACEd8B2F0aebE155379bb5D594381': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'ethereum', - symbol: 'APE' - }, - banxa: { - network: 'ETH', - symbol: 'APE' - } - }, - network: 'ethereum', - slug: 'ethereum-ERC20-APE-0x4d224452801ACEd8B2F0aebE155379bb5D594381', - symbol: 'APE', - support: 'ETHEREUM', - services: [ - 'transak', - 'banxa' - ] - }, - 'ethereum-ERC20-BAT-0x0D8775F648430679A709E98d2b0Cb6250d2887EF': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'ethereum', - symbol: 'BAT' - }, - banxa: { - network: 'ETH', - symbol: 'BAT' - } - }, - network: 'ethereum', - slug: 'ethereum-ERC20-BAT-0x0D8775F648430679A709E98d2b0Cb6250d2887EF', - symbol: 'BAT', - support: 'ETHEREUM', - services: [ - 'transak', - 'banxa' - ] - }, - 'boba-ERC20-BOBA-0xa18bf3994c0cc6e3b63ac420308e5383f53120d7': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - banxa: { - network: 'BOBA', - symbol: 'BOBA' - } - }, - network: 'boba', - slug: 'boba-ERC20-BOBA-0xa18bf3994c0cc6e3b63ac420308e5383f53120d7', - symbol: 'BOBA', - support: 'ETHEREUM', - services: [ - 'banxa' - ] - }, - 'binance-ERC20-BUSD-0xe9e7cea3dedca5984780bafc599bd69add087d56': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'bsc', - symbol: 'BUSD' - } - }, - network: 'binance', - slug: 'binance-ERC20-BUSD-0xe9e7cea3dedca5984780bafc599bd69add087d56', - symbol: 'BUSD', - support: 'ETHEREUM', - services: [ - 'transak' - ] - }, - 'ethereum-ERC20-BUSD-0x4Fabb145d64652a948d72533023f6E7A623C7C53': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'ethereum', - symbol: 'BUSD' - }, - banxa: { - network: 'ETH', - symbol: 'BUSD' - } - }, - network: 'ethereum', - slug: 'ethereum-ERC20-BUSD-0x4Fabb145d64652a948d72533023f6E7A623C7C53', - symbol: 'BUSD', - support: 'ETHEREUM', - services: [ - 'transak', - 'banxa' - ] - }, - 'ethereum-ERC20-CHZ-0x3506424F91fD33084466F402d5D97f05F8e3b4AF': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - banxa: { - network: 'ETH', - symbol: 'CHZ' - } - }, - network: 'ethereum', - slug: 'ethereum-ERC20-CHZ-0x3506424F91fD33084466F402d5D97f05F8e3b4AF', - symbol: 'CHZ', - support: 'ETHEREUM', - services: [ - 'banxa' - ] - }, - 'ethereum-ERC20-COMP-0xc00e94Cb662C3520282E6f5717214004A7f26888': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'ethereum', - symbol: 'COMP' - }, - banxa: { - network: 'ETH', - symbol: 'COMP' - } - }, - network: 'ethereum', - slug: 'ethereum-ERC20-COMP-0xc00e94Cb662C3520282E6f5717214004A7f26888', - symbol: 'COMP', - support: 'ETHEREUM', - services: [ - 'transak', - 'banxa' - ] - }, - 'binance-ERC20-Cake-0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - banxa: { - network: 'BSC', - symbol: 'CAKE' - } - }, - network: 'binance', - slug: 'binance-ERC20-Cake-0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82', - symbol: 'Cake', - support: 'ETHEREUM', - services: [ - 'banxa' - ] - }, - 'ethereum-ERC20-DAI-0x6B175474E89094C44Da98b954EedeAC495271d0F': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'ethereum', - symbol: 'DAI' - }, - banxa: { - network: 'ETH', - symbol: 'DAI' - }, - coinbase: { - network: 'ethereum', - symbol: 'DAI' - } - }, - network: 'ethereum', - slug: 'ethereum-ERC20-DAI-0x6B175474E89094C44Da98b954EedeAC495271d0F', - symbol: 'DAI', - support: 'ETHEREUM', - services: [ - 'transak', - 'banxa', - 'coinbase' - ] - }, - 'ethereum-ERC20-ENJ-0xF629cBd94d3791C9250152BD8dfBDF380E2a3B9c': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - banxa: { - network: 'ETH', - symbol: 'ENJ' - } - }, - network: 'ethereum', - slug: 'ethereum-ERC20-ENJ-0xF629cBd94d3791C9250152BD8dfBDF380E2a3B9c', - symbol: 'ENJ', - support: 'ETHEREUM', - services: [ - 'banxa' - ] - }, - 'ethereum-ERC20-LINK-0x514910771AF9Ca656af840dff83E8264EcF986CA': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'ethereum', - symbol: 'LINK' - }, - banxa: { - network: 'ETH', - symbol: 'LINK' - } - }, - network: 'ethereum', - slug: 'ethereum-ERC20-LINK-0x514910771AF9Ca656af840dff83E8264EcF986CA', - symbol: 'LINK', - support: 'ETHEREUM', - services: [ - 'transak', - 'banxa' - ] - }, - 'ethereum-ERC20-MATIC-0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - coinbase: { - network: 'ethereum', - symbol: 'MATIC' - } - }, - network: 'ethereum', - slug: 'ethereum-ERC20-MATIC-0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0', - symbol: 'MATIC', - support: 'ETHEREUM', - services: [ - 'coinbase' - ] - }, - 'ethereum-ERC20-MKR-0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'ethereum', - symbol: 'MKR' - }, - banxa: { - network: 'ETH', - symbol: 'MKR' - } - }, - network: 'ethereum', - slug: 'ethereum-ERC20-MKR-0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2', - symbol: 'MKR', - support: 'ETHEREUM', - services: [ - 'transak', - 'banxa' - ] - }, - 'optimism-ERC20-OP-0x4200000000000000000000000000000000000042': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - coinbase: { - network: 'optimism', - symbol: 'OP' - } - }, - network: 'optimism', - slug: 'optimism-ERC20-OP-0x4200000000000000000000000000000000000042', - symbol: 'OP', - support: 'ETHEREUM', - services: [ - 'coinbase' - ] - }, - 'ethereum-ERC20-SAND-0x3845badAde8e6dFF049820680d1F14bD3903a5d0': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'ethereum', - symbol: 'SAND' - }, - banxa: { - network: 'ETH', - symbol: 'SAND' - } - }, - network: 'ethereum', - slug: 'ethereum-ERC20-SAND-0x3845badAde8e6dFF049820680d1F14bD3903a5d0', - symbol: 'SAND', - support: 'ETHEREUM', - services: [ - 'transak', - 'banxa' - ] - }, - 'ethereum-ERC20-UNI-0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'ethereum', - symbol: 'UNI' - } - }, - network: 'ethereum', - slug: 'ethereum-ERC20-UNI-0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984', - symbol: 'UNI', - support: 'ETHEREUM', - services: [ - 'transak' - ] - }, - 'arbitrum_one-ERC20-USDC-0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'arbitrum', - symbol: 'USDC' - } - }, - network: 'arbitrum_one', - slug: 'arbitrum_one-ERC20-USDC-0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', - symbol: 'USDC', - support: 'ETHEREUM', - services: [ - 'transak' - ] - }, - 'binance-ERC20-USDC-0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'bsc', - symbol: 'USDC' - } - }, - network: 'binance', - slug: 'binance-ERC20-USDC-0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d', - symbol: 'USDC', - support: 'ETHEREUM', - services: [ - 'transak' - ] - }, - 'ethereum-ERC20-USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'ethereum', - symbol: 'USDC' - }, - banxa: { - network: 'ETH', - symbol: 'USDC' - } - }, - network: 'ethereum', - slug: 'ethereum-ERC20-USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', - symbol: 'USDC', - support: 'ETHEREUM', - services: [ - 'transak', - 'banxa' - ] - }, - 'polygon-ERC20-USDC-0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'polygon', - symbol: 'USDC' - } - }, - network: 'polygon', - slug: 'polygon-ERC20-USDC-0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', - symbol: 'USDC', - support: 'ETHEREUM', - services: [ - 'transak' - ] - }, - 'binance-ERC20-USDT-0x55d398326f99059fF775485246999027B3197955': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'bsc', - symbol: 'USDT' - } - }, - network: 'binance', - slug: 'binance-ERC20-USDT-0x55d398326f99059fF775485246999027B3197955', - symbol: 'USDT', - support: 'ETHEREUM', - services: [ - 'transak' - ] - }, - 'ethereum-ERC20-USDT-0xdAC17F958D2ee523a2206206994597C13D831ec7': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'ethereum', - symbol: 'USDT' - }, - banxa: { - network: 'ETH', - symbol: 'USDT' - } - }, - network: 'ethereum', - slug: 'ethereum-ERC20-USDT-0xdAC17F958D2ee523a2206206994597C13D831ec7', - symbol: 'USDT', - support: 'ETHEREUM', - services: [ - 'transak', - 'banxa' - ] - }, - 'polygon-ERC20-USDT-0xc2132D05D31c914a87C6611C10748AEb04B58e8F': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'polygon', - symbol: 'USDT' - } - }, - network: 'polygon', - slug: 'polygon-ERC20-USDT-0xc2132D05D31c914a87C6611C10748AEb04B58e8F', - symbol: 'USDT', - support: 'ETHEREUM', - services: [ - 'transak' - ] - }, - 'ethereum-ERC20-VERSE-0x249cA82617eC3DfB2589c4c17ab7EC9765350a18': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'ethereum', - symbol: 'VERSE' - } - }, - network: 'ethereum', - slug: 'ethereum-ERC20-VERSE-0x249cA82617eC3DfB2589c4c17ab7EC9765350a18', - symbol: 'VERSE', - support: 'ETHEREUM', - services: [ - 'transak' - ] - }, - 'ethereum-ERC20-WBTC-0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599': { - serviceInfo: { - ...DEFAULT_SERVICE_INFO, - transak: { - network: 'ethereum', - symbol: 'WBTC' - }, - coinbase: { - network: 'ethereum', - symbol: 'WBTC' - } - }, - network: 'ethereum', - slug: 'ethereum-ERC20-WBTC-0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', - symbol: 'WBTC', - support: 'ETHEREUM', - services: [ - 'transak', - 'coinbase' - ] - } -}; - -export const LIST_PREDEFINED_BUY_TOKEN = Object.values(MAP_PREDEFINED_BUY_TOKEN); diff --git a/packages/extension-base/src/services/buy-service/index.ts b/packages/extension-base/src/services/buy-service/index.ts index 0a08f4791f..be0d0adea0 100644 --- a/packages/extension-base/src/services/buy-service/index.ts +++ b/packages/extension-base/src/services/buy-service/index.ts @@ -3,11 +3,12 @@ import { BUY_SERVICE_CONTACT_URL, BUY_TOKEN_URL } from '@subwallet/extension-base/constants'; import KoniState from '@subwallet/extension-base/koni/background/handlers/State'; -import { BuyServiceInfo, BuyTokenInfo } from '@subwallet/extension-base/types'; +import { ListBuyServicesResponse, ListBuyTokenResponse } from '@subwallet/extension-base/services/buy-service/types'; +import { BuyServiceInfo, BuyTokenInfo, SupportService } from '@subwallet/extension-base/types'; import axios from 'axios'; import { BehaviorSubject } from 'rxjs'; -import { BUY_SERVICE_CONTACTS, MAP_PREDEFINED_BUY_TOKEN } from './constants'; +import { DEFAULT_SERVICE_INFO } from './constants'; export default class BuyService { readonly #state: KoniState; @@ -40,9 +41,43 @@ export default class BuyService { url: BUY_TOKEN_URL }); - console.log(response); + const data = response.data as ListBuyTokenResponse; - this.buyTokensSubject.next(MAP_PREDEFINED_BUY_TOKEN); + const result: Record = {}; + + for (const datum of data) { + const temp: BuyTokenInfo = { + serviceInfo: { + ...DEFAULT_SERVICE_INFO + }, + support: datum.support, + services: [], + slug: datum.slug, + symbol: datum.symbol, + network: datum.network + }; + + for (const [_service, info] of Object.entries(datum.serviceInfo)) { + const service = _service as SupportService; + + if (info.isSuspended) { + continue; + } + + temp.serviceInfo[service] = { + network: info.network, + symbol: info.symbol + }; + + temp.services.push(service); + } + + if (temp.services.length) { + result[temp.slug] = temp; + } + } + + this.buyTokensSubject.next(result); this.#state.eventService.emit('buy.tokens.ready', true); } @@ -53,9 +88,17 @@ export default class BuyService { url: BUY_SERVICE_CONTACT_URL }); - console.log(response); + const data = response.data as ListBuyServicesResponse; + + const result: Record = {}; + + for (const datum of data) { + const { id, slug, ...info } = datum; + + result[slug] = { ...info }; + } - this.buyServicesSubject.next(BUY_SERVICE_CONTACTS); + this.buyServicesSubject.next(result); this.#state.eventService.emit('buy.services.ready', true); } diff --git a/packages/extension-base/src/services/buy-service/types.ts b/packages/extension-base/src/services/buy-service/types.ts index a8ec91339c..3f16995c83 100644 --- a/packages/extension-base/src/services/buy-service/types.ts +++ b/packages/extension-base/src/services/buy-service/types.ts @@ -1,41 +1,25 @@ // Copyright 2019-2022 @subwallet/extension-koni authors & contributors // SPDX-License-Identifier: Apache-2.0 -import { CampaignAction, CampaignButton } from '@subwallet/extension-base/background/KoniTypes'; +import { BuyService, BuyTokenInfo, SupportService } from '@subwallet/extension-base/types'; -type Metadata = Record | null; - -interface _BannerData { - id: number; - alt: string; - action: CampaignAction; - metadata: Metadata; - environments: string[]; - position: string[]; - buttons: CampaignButton[]; - media: string; -} - -interface _NotificationData { - id: number; - title: string; - message: string; - repeat: number; - repeatAfter: number; - action: CampaignAction; - metadata: Metadata; - buttons: CampaignButton[]; +interface _BuyTokenInfo { + serviceInfo: Record; + network: string; + slug: string; + symbol: string; + support: BuyTokenInfo['support']; } -interface _CampaignData { +interface _BuyServiceInfo { id: number; name: string; - description: null; - start_time: string; - end_time: string; - condition: Metadata; - banners: _BannerData[]; - notifications: _NotificationData[]; + contactUrl: string; + termUrl: string; + policyUrl: string; + url: string; + slug: SupportService; } -export type ListCampaignResponse = _CampaignData[] +export type ListBuyTokenResponse = _BuyTokenInfo[]; +export type ListBuyServicesResponse = _BuyServiceInfo[]; diff --git a/packages/extension-koni/webpack.shared.cjs b/packages/extension-koni/webpack.shared.cjs index 25d50d6fce..2007bb413a 100644 --- a/packages/extension-koni/webpack.shared.cjs +++ b/packages/extension-koni/webpack.shared.cjs @@ -43,6 +43,8 @@ const _additionalEnv = { TRANSAK_API_KEY: JSON.stringify(process.env.TRANSAK_API_KEY), COINBASE_PAY_ID: JSON.stringify(process.env.COINBASE_PAY_ID), MARKETING_CAMPAIGN_URL: JSON.stringify(process.env.MARKETING_CAMPAIGN_URL), + BUY_TOKEN_URL: JSON.stringify(process.env.BUY_TOKEN_URL), + BUY_SERVICE_CONTACT_URL: JSON.stringify(process.env.BUY_SERVICE_CONTACT_URL), TRANSAK_TEST_MODE: JSON.stringify(false), BANXA_TEST_MODE: JSON.stringify(false) }; From 98e99a86bbc5f3b6d6c622f38fe62ac5e908e9c8 Mon Sep 17 00:00:00 2001 From: S2kael Date: Fri, 27 Oct 2023 10:54:07 +0700 Subject: [PATCH 3/9] [Issue-2025] Config env for web-runner --- packages/web-runner/webpack.config.cjs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/web-runner/webpack.config.cjs b/packages/web-runner/webpack.config.cjs index f9f5f581c5..e7df4e2967 100644 --- a/packages/web-runner/webpack.config.cjs +++ b/packages/web-runner/webpack.config.cjs @@ -13,6 +13,7 @@ module.exports = { const path = require('path'); const webpack = require('webpack'); +const dotenv = require('dotenv'); const CopyPlugin = require('copy-webpack-plugin'); @@ -32,6 +33,10 @@ if (args) { console.log('You are using ' + mode + ' mode.'); +const envPath = mode === 'production' ? '.env' : '.env.local'; + +dotenv.config({ path: `../../${envPath}` }); + const packages = [ 'extension-base', 'extension-chains', @@ -42,6 +47,13 @@ const packages = [ ]; const polkadotDevOptions = require('@polkadot/dev/config/babel-config-webpack.cjs'); + +const _additionalEnv = { + MARKETING_CAMPAIGN_URL: JSON.stringify(process.env.MARKETING_CAMPAIGN_URL), + BUY_TOKEN_URL: JSON.stringify(process.env.BUY_TOKEN_URL), + BUY_SERVICE_CONTACT_URL: JSON.stringify(process.env.BUY_SERVICE_CONTACT_URL) +}; + // Overwrite babel babel config from polkadot dev const createConfig = (entry, alias = {}, useSplitChunk = false) => { @@ -106,7 +118,8 @@ const createConfig = (entry, alias = {}, useSplitChunk = false) => { NODE_ENV: JSON.stringify(mode), PKG_NAME: JSON.stringify(pkgJson.name), PKG_VERSION: JSON.stringify(pkgJson.version), - TARGET_ENV: JSON.stringify('mobile') + TARGET_ENV: JSON.stringify('mobile'), + ..._additionalEnv } }), new CopyPlugin({ From 2c7b97513dcb24b025aa60569cc33e8fa95f576a Mon Sep 17 00:00:00 2001 From: lw-cdm Date: Tue, 31 Oct 2023 16:35:49 +0700 Subject: [PATCH 4/9] [Issue-2104] Fix UI bug on token detail screen --- .../Popup/Home/Tokens/DetailUpperBlock.tsx | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/packages/extension-koni-ui/src/Popup/Home/Tokens/DetailUpperBlock.tsx b/packages/extension-koni-ui/src/Popup/Home/Tokens/DetailUpperBlock.tsx index cd05eb2bb1..ea5b6dddd6 100644 --- a/packages/extension-koni-ui/src/Popup/Home/Tokens/DetailUpperBlock.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/Tokens/DetailUpperBlock.tsx @@ -2,12 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 import { useTranslation } from '@subwallet/extension-koni-ui/hooks'; +import { saveShowBalance } from '@subwallet/extension-koni-ui/messaging'; import { RootState } from '@subwallet/extension-koni-ui/stores'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; import { Button, Icon, Number } from '@subwallet/react-ui'; import { SwNumberProps } from '@subwallet/react-ui/es/number'; import { CaretLeft, CopySimple, PaperPlaneTilt, ShoppingCartSimple } from 'phosphor-react'; -import React from 'react'; +import React, { useCallback } from 'react'; import { useSelector } from 'react-redux'; import styled from 'styled-components'; @@ -35,6 +36,10 @@ function Component ( const { t } = useTranslation(); const { isShowBalance } = useSelector((state: RootState) => state.settings); + const onChangeShowBalance = useCallback(() => { + saveShowBalance(!isShowBalance).catch(console.error); + }, [isShowBalance]); + return (
@@ -53,16 +58,21 @@ function Component (
{t('Token')}: {symbol}
- +
+ +