Skip to content

Commit

Permalink
feat: coinbase pay sdk integration (#1487)
Browse files Browse the repository at this point in the history
Co-authored-by: Neel Ramachandran <neel.ramachandran@coinbase.com>
Co-authored-by: 0xAsimetriq <idaderko@gmail.com>
Co-authored-by: tomiir <rocchitomas@gmail.com>
Co-authored-by: Derek <alexanderderekrein@gmail.com>
  • Loading branch information
5 people committed Feb 7, 2024
1 parent 7186d23 commit 3b0eafb
Show file tree
Hide file tree
Showing 82 changed files with 2,226 additions and 163 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"**/out": true,
"**/dist": true,
"**/.turbo": true,
"**/playwright-report": true
"**/playwright-report": true,
"**/coverage": true
},
"javascript.updateImportsOnFileMove.enabled": "always",
"typescript.tsdk": "node_modules/typescript/lib",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { Meta } from '@storybook/web-components'
import '@web3modal/ui/src/composites/wui-onramp-activity-item'
import type { WuiOnRampActivityItem } from '@web3modal/ui/src/composites/wui-onramp-activity-item'
import { html } from 'lit'
import '../../components/gallery-container'

type Component = Meta<WuiOnRampActivityItem>

export default {
title: 'Composites/wui-onramp-activity-item',
args: {
completed: true,
inProgress: false,
failed: false,
purchaseCurrency: 'USD',
purchaseValue: '1000',
date: '2 days ago'
}
} as Component

export const Default: Component = {
render: args => html`
<gallery-container width="340">
<wui-onramp-activity-item
label="Bought"
.completed=${args.completed}
.inProgress=${args.inProgress}
.failed=${args.failed}
purchaseCurrency=${args.purchaseCurrency}
purchaseValue=${args.purchaseValue}
date=${args.date}
></wui-onramp-activity-item>
</gallery-container>
`
}
9 changes: 7 additions & 2 deletions apps/gallery/utils/PresetUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ export const textOptions: TextType[] = [
'paragraph-700',
'large-500',
'large-600',
'large-700'
'large-700',
'2xl-500'
]

export const textAlignOptions: TextAlign[] = ['center', 'left', 'right']
Expand Down Expand Up @@ -225,7 +226,11 @@ export const visualOptions: VisualType[] = [
'nft',
'noun',
'profile',
'system'
'system',
'coinbase',
'stripe',
'moonpay',
'paypal'
]

export const logoOptions: LogoType[] = [
Expand Down
3 changes: 2 additions & 1 deletion apps/laboratory/src/pages/library/ethers-email.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ const modal = createWeb3Modal({
enableAnalytics: true,
metadata: ConstantsUtil.Metadata,
termsConditionsUrl: 'https://walletconnect.com/terms',
privacyPolicyUrl: 'https://walletconnect.com/privacy'
privacyPolicyUrl: 'https://walletconnect.com/privacy',
enableOnramp: true
})

ThemeStore.setModal(modal)
Expand Down
3 changes: 2 additions & 1 deletion apps/laboratory/src/pages/library/ethers-siwe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ const modal = createWeb3Modal({
projectId: ConstantsUtil.ProjectId,
enableAnalytics: true,
metadata: ConstantsUtil.Metadata,
siweConfig
siweConfig,
enableOnramp: true
})

ThemeStore.setModal(modal)
Expand Down
3 changes: 2 additions & 1 deletion apps/laboratory/src/pages/library/ethers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ const modal = createWeb3Modal({
desktop_link: 'https://react-wallet.walletconnect.com',
webapp_link: 'https://react-wallet.walletconnect.com'
}
]
],
enableOnramp: true
})

ThemeStore.setModal(modal)
Expand Down
3 changes: 2 additions & 1 deletion apps/laboratory/src/pages/library/wagmi-email.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ const modal = createWeb3Modal({
enableAnalytics: true,
metadata: ConstantsUtil.Metadata,
termsConditionsUrl: 'https://walletconnect.com/terms',
privacyPolicyUrl: 'https://walletconnect.com/privacy'
privacyPolicyUrl: 'https://walletconnect.com/privacy',
enableOnramp: true
})

ThemeStore.setModal(modal)
Expand Down
3 changes: 2 additions & 1 deletion apps/laboratory/src/pages/library/wagmi-siwe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ const modal = createWeb3Modal({
projectId: ConstantsUtil.ProjectId,
enableAnalytics: true,
metadata: ConstantsUtil.Metadata,
siweConfig
siweConfig,
enableOnramp: true
})

ThemeStore.setModal(modal)
Expand Down
3 changes: 2 additions & 1 deletion apps/laboratory/src/pages/library/wagmi.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ const modal = createWeb3Modal({
desktop_link: 'https://react-wallet.walletconnect.com',
webapp_link: 'https://react-wallet.walletconnect.com'
}
]
],
enableOnramp: true
})

ThemeStore.setModal(modal)
Expand Down
25 changes: 21 additions & 4 deletions dangerfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,31 @@ async function checkUiPackage() {
fail('New layout components were added, but not exported in ui/index.ts')
}

if (created_ui_components_index_ts.length && !jsx_index_diff?.added.includes('../components')) {
fail('New components were added, but not exported in ui/utils/JSXTypeUtil.ts')
if (
created_ui_components_index_ts.length &&
!jsx_index_diff?.added.includes('../components') &&
!jsx_index_diff?.diff.includes('../components')
) {
fail(
`New components were added, but not exported in ui/utils/JSXTypeUtil.ts: ${created_ui_components.join(
', '
)}`
)
}

if (created_ui_composites_index_ts.length && !jsx_index_diff?.added.includes('../composites')) {
if (
created_ui_composites_index_ts.length &&
!jsx_index_diff?.added.includes('../composites') &&
!jsx_index_diff?.diff.includes('../composites')
) {
fail('New composites were added, but not exported in ui/utils/JSXTypeUtil.ts')
}

if (created_ui_layout_index_ts.length && !jsx_index_diff?.added.includes('../layout')) {
if (
created_ui_layout_index_ts.length &&
!jsx_index_diff?.added.includes('../layout') &&
!jsx_index_diff?.diff.includes('../layout')
) {
fail('New layout components were added, but not exported in ui/utils/JSXTypeUtil.ts')
}

Expand Down Expand Up @@ -277,6 +293,7 @@ checkSdkVersion()
async function checkDevelopmentConstants() {
for (const f of updated_files) {
if (f.includes('README.md') || f.includes('.yml')) {
// eslint-disable-next-line no-continue
continue
}
const diff = await diffForFile(f)
Expand Down
7 changes: 6 additions & 1 deletion packages/common/src/utils/TypeUtil.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
export type CoinbaseTransactionStatus =
| 'ONRAMP_TRANSACTION_STATUS_SUCCESS'
| 'ONRAMP_TRANSACTION_STATUS_IN_PROGRESS'
| 'ONRAMP_TRANSACTION_STATUS_FAILED'

export type TransactionStatus = 'confirmed' | 'failed' | 'pending'

export type TransactionDirection = 'in' | 'out' | 'self'
Expand All @@ -19,7 +24,7 @@ export interface TransactionMetadata {
minedAt: string
sentFrom: string
sentTo: string
status: TransactionStatus
status: TransactionStatus | CoinbaseTransactionStatus
nonce: number
}

Expand Down
3 changes: 3 additions & 0 deletions packages/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ export type {
NetworkControllerState
} from './src/controllers/NetworkController.js'

export { OnRampController } from './src/controllers/OnRampController.js'
export type { OnRampControllerState, OnRampProvider } from './src/controllers/OnRampController.js'

export { ConnectionController } from './src/controllers/ConnectionController.js'
export type {
ConnectionControllerClient,
Expand Down
41 changes: 38 additions & 3 deletions packages/core/src/controllers/BlockchainApiController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ import type {
} from '../utils/TypeUtil.js'
import { OptionsController } from './OptionsController.js'

type DestinationWallet = {
address: string
blockchains: string[]
assets: string[]
}

type GenerateOnRampT = {
destinationWallets: DestinationWallet[]
partnerUserId: string
defaultNetwork?: string
}

// -- Helpers ------------------------------------------- //
const baseUrl = CoreHelperUtil.getBlockchainApiUrl()
const api = new FetchUtil({ baseUrl })
Expand All @@ -24,12 +36,35 @@ export const BlockchainApiController = {
})
},

fetchTransactions({ account, projectId, cursor }: BlockchainApiTransactionsRequest) {
fetchTransactions({
account,
projectId,
cursor,
onramp,
signal
}: BlockchainApiTransactionsRequest) {
const queryParams = cursor ? { cursor } : {}

return api.get<BlockchainApiTransactionsResponse>({
path: `/v1/account/${account}/history?projectId=${projectId}`,
params: queryParams
path: `/v1/account/${account}/history?projectId=${projectId}${
onramp ? `&onramp=${onramp}` : ''
}`,
params: queryParams,
signal
})
},

async generateOnRampURL({ destinationWallets, partnerUserId, defaultNetwork }: GenerateOnRampT) {
const response = await api.post<{ url: string }>({
path: `/v1/generators/onrampurl?projectId=${OptionsController.state.projectId}`,
body: {
destinationWallets,
defaultNetwork,
partnerUserId,
defaultExperience: 'buy'
}
})

return response.url
}
}
10 changes: 10 additions & 0 deletions packages/core/src/controllers/NetworkController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { CaipNetwork, CaipNetworkId } from '../utils/TypeUtil.js'
import { PublicStateController } from './PublicStateController.js'
import { EventsController } from './EventsController.js'
import { ModalController } from './ModalController.js'
import { CoreHelperUtil } from '../utils/CoreHelperUtil.js'

// -- Types --------------------------------------------- //
export interface NetworkControllerClient {
Expand Down Expand Up @@ -68,6 +69,15 @@ export const NetworkController = {
state.requestedCaipNetworks = requestedNetworks
},

getRequestedCaipNetworks() {
const { approvedCaipNetworkIds, requestedCaipNetworks } = state

const approvedIds = approvedCaipNetworkIds
const requestedNetworks = requestedCaipNetworks

return CoreHelperUtil.sortRequestedNetworks(approvedIds, requestedNetworks)
},

async getApprovedCaipNetworksData() {
const data = await this._getClient().getApprovedCaipNetworksData()
state.supportsAllNetworks = data.supportsAllNetworks
Expand Down
41 changes: 41 additions & 0 deletions packages/core/src/controllers/OnRampController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { subscribeKey as subKey } from 'valtio/utils'
import { proxy } from 'valtio/vanilla'
import { ONRAMP_PROVIDERS } from '../utils/ConstantsUtil.js'

// -- Types --------------------------------------------- //
export type OnRampProviderOption = 'coinbase' | 'moonpay' | 'stripe' | 'paypal'

export type OnRampProvider = {
label: string
name: OnRampProviderOption
feeRange: string
url: string
}

export interface OnRampControllerState {
providers: OnRampProvider[]
selectedProvider: OnRampProvider | null
error: string | null
}

type StateKey = keyof OnRampControllerState

// -- State --------------------------------------------- //
const state = proxy<OnRampControllerState>({
providers: ONRAMP_PROVIDERS as OnRampProvider[],
selectedProvider: null,
error: null
})

// -- Controller ---------------------------------------- //
export const OnRampController = {
state,

subscribeKey<K extends StateKey>(key: K, callback: (value: OnRampControllerState[K]) => void) {
return subKey(state, key, callback)
},

setSelectedProvider(provider: OnRampProvider | null) {
state.selectedProvider = provider
}
}
9 changes: 7 additions & 2 deletions packages/core/src/controllers/OptionsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import type { CustomWallet, Metadata, ProjectId, SdkVersion, Tokens } from '../u
// -- Types --------------------------------------------- //
export interface OptionsControllerState {
projectId: ProjectId
sdkType: 'w3m'
sdkVersion: SdkVersion
allWallets?: 'SHOW' | 'HIDE' | 'ONLY_MOBILE'
featuredWalletIds?: string[]
includeWalletIds?: string[]
Expand All @@ -15,8 +17,7 @@ export interface OptionsControllerState {
privacyPolicyUrl?: string
enableAnalytics?: boolean
metadata?: Metadata
sdkType: 'w3m'
sdkVersion: SdkVersion
enableOnramp?: boolean
}

type StateKey = keyof OptionsControllerState
Expand Down Expand Up @@ -82,5 +83,9 @@ export const OptionsController = {

setMetadata(metadata: OptionsControllerState['metadata']) {
state.metadata = metadata
},

setOnrampEnabled(enableOnramp: OptionsControllerState['enableOnramp']) {
state.enableOnramp = enableOnramp
}
}
23 changes: 14 additions & 9 deletions packages/core/src/controllers/RouterController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,31 @@ import type { CaipNetwork, Connector, WcWallet } from '../utils/TypeUtil.js'
export interface RouterControllerState {
view:
| 'Account'
| 'AccountSettings'
| 'AllWallets'
| 'ApproveTransaction'
| 'BuyInProgress'
| 'Connect'
| 'ConnectingExternal'
| 'ConnectingWalletConnect'
| 'ConnectingSiwe'
| 'Networks'
| 'SwitchNetwork'
| 'AllWallets'
| 'WhatIsAWallet'
| 'WhatIsANetwork'
| 'GetWallet'
| 'Downloads'
| 'EmailVerifyOtp'
| 'EmailVerifyDevice'
| 'ApproveTransaction'
| 'GetWallet'
| 'Networks'
| 'OnRampProviders'
| 'OnRampActivity'
| 'SwitchNetwork'
| 'Transactions'
| 'UpgradeEmailWallet'
| 'UnsupportedChain'
| 'UpdateEmailWallet'
| 'UpdateEmailPrimaryOtp'
| 'UpdateEmailSecondaryOtp'
| 'UnsupportedChain'
| 'UpgradeEmailWallet'
| 'WhatIsABuy'
| 'WhatIsANetwork'
| 'WhatIsAWallet'
history: RouterControllerState['view'][]
data?: {
connector?: Connector
Expand Down
Loading

1 comment on commit 3b0eafb

@Jircs1
Copy link

@Jircs1 Jircs1 commented on 3b0eafb Feb 13, 2024

Choose a reason for hiding this comment

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

😃

Please sign in to comment.