Skip to content

Commit

Permalink
feat: Grant contract-call permission UI (#3082)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomiir authored Oct 16, 2024
1 parent d23fc22 commit bbc48bc
Show file tree
Hide file tree
Showing 17 changed files with 231 additions and 8 deletions.
23 changes: 23 additions & 0 deletions .changeset/great-poets-tickle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
'@reown/appkit-experimental': patch
'@reown/appkit-scaffold-ui': patch
'@apps/laboratory': patch
'@reown/appkit-core': patch
'@reown/appkit-ui': patch
'@apps/demo': patch
'@apps/gallery': patch
'@reown/appkit-adapter-ethers': patch
'@reown/appkit-adapter-ethers5': patch
'@reown/appkit-adapter-polkadot': patch
'@reown/appkit-adapter-solana': patch
'@reown/appkit-adapter-wagmi': patch
'@reown/appkit': patch
'@reown/appkit-utils': patch
'@reown/appkit-cdn': patch
'@reown/appkit-common': patch
'@reown/appkit-polyfills': patch
'@reown/appkit-siwe': patch
'@reown/appkit-wallet': patch
---

Adds wui-permission-contract-call to experimental package. Adds w3m-smart-session-created-view to experimental package
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export function WagmiRequestPermissionsAsyncTest() {
</Text>
)
}

if (!isSupported) {
return (
<Text fontSize="md" color="yellow">
Expand Down
2 changes: 1 addition & 1 deletion packages/appkit/exports/constants.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const PACKAGE_VERSION = '1.1.2'
export const PACKAGE_VERSION = '1.1.3'
1 change: 1 addition & 0 deletions packages/core/src/controllers/RouterController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export interface RouterControllerState {
| 'SwapPreview'
| 'ConnectingMultiChain'
| 'SwitchActiveChain'
| 'SmartSessionCreated'
history: RouterControllerState['view'][]
data?: {
connector?: Connector
Expand Down
4 changes: 4 additions & 0 deletions packages/experimental/exports/smart-session/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@ export {
} from '../../src/smart-session/grantPermissions.js'

export * from '../../src/smart-session/utils/TypeUtils.js'

// Views
export * from '../../src/smart-session/ui/views/w3m-smart-session-created-view/index.js'
export * from '../../src/smart-session/ui/permissions/wui-permission-contract-call/index.js'
4 changes: 3 additions & 1 deletion packages/experimental/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@
"@reown/appkit": "workspace:*",
"@reown/appkit-core": "workspace:*",
"@reown/appkit-common": "workspace:*",
"@reown/appkit-ui": "workspace:*",
"axios": "1.7.2",
"zod": "3.22.4"
"zod": "3.22.4",
"lit": "3.1.0"
},
"devDependencies": {
"@types/axios-mock-adapter": "1.10.0",
Expand Down
13 changes: 11 additions & 2 deletions packages/experimental/src/smart-session/grantPermissions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { ChainController, ConnectionController, OptionsController } from '@reown/appkit-core'
import {
ChainController,
ConnectionController,
OptionsController,
RouterController
} from '@reown/appkit-core'
import { ProviderUtil } from '@reown/appkit/store'
import { ConstantsUtil as CommonConstantsUtil } from '@reown/appkit-common'
import type {
Expand Down Expand Up @@ -74,6 +79,11 @@ export async function grantPermissions(
// Update request signer with the cosigner key
updateRequestSigner(request, addPermissionResponse.key)

RouterController.pushTransactionStack({
view: 'SmartSessionCreated',
goBack: false
})

const rawResponse = await connectionControllerClient.grantPermissions([request])

// Validate and type guard the response
Expand Down Expand Up @@ -126,7 +136,6 @@ export function validateRequestForSupportedPermissionsCapability(

export function isSmartSessionSupported(): boolean {
const provider = ProviderUtil.getProvider(CommonConstantsUtil.CHAIN.EVM)

if (!provider) {
return false
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { customElement, UiHelperUtil } from '@reown/appkit-ui'
import { LitElement, html } from 'lit'
import styles from './styles.js'
import { property } from 'lit/decorators.js'

@customElement('wui-permission-contract-call')
export class WuiPermissionContractCall extends LitElement {
// -- State & Properties --------------------------------- //
public static override styles = styles

@property({ type: Array }) public functions?: { functionName: string }[] = []
@property({ type: String }) public contractAddress?: `0x${string}`
@property({ type: Number }) public expiry?: number

// -- Render -------------------------------------------- //
public override render() {
if (!this.contractAddress || !this.expiry) {
return null
}

return html`
<wui-flex flexDirection="column" padding=${['l', '0', '0', '0']} alignItems="center">
<wui-details-group>
<wui-details-group-item name="Type">
<wui-text variant="paragraph-400" color="fg-100"> Contract Call </wui-text>
</wui-details-group-item>
<wui-details-group-item name="Contract">
<wui-text variant="paragraph-400" color="fg-100">
${UiHelperUtil.getTruncateString({
string: this.contractAddress,
truncate: 'middle',
charsStart: 4,
charsEnd: 4
})}
</wui-text>
</wui-details-group-item>
<wui-details-group-item name="Functions">
<wui-text variant="paragraph-400" color="fg-100">
${this.functions?.map(f => f.functionName).join(', ')}
</wui-text>
</wui-details-group-item>
<wui-flex justifyContent="space-between">
<wui-text color="fg-200">Duration</wui-text>
<wui-flex flexDirection="column" alignItems="flex-end" gap="s">
<wui-text variant="paragraph-400" color="fg-100">
~ ${Math.round((1000 * this.expiry - Date.now()) / 1000 / 3600)} hours
</wui-text>
<wui-text variant="tiny-600" color="fg-300">
Expiring ${new Date(1000 * this.expiry).toDateString()}
</wui-text>
</wui-flex>
</wui-flex>
</wui-details-group>
</wui-flex>
`
}
}

declare global {
interface HTMLElementTagNameMap {
'wui-permission-contract-call': WuiPermissionContractCall
}

namespace JSX {
interface IntrinsicElements {
'wui-permission-contract-call': Partial<WuiPermissionContractCall>
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { css } from 'lit'

// First wui-flex should be width: 100%
export default css`
:host {
width: 100%;
}
wui-flex {
width: 100%;
}
`
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { customElement } from '@reown/appkit-ui'
import { CoreHelperUtil, RouterController } from '@reown/appkit-core'
import { LitElement, html } from 'lit'
import styles from './styles.js'
import { NavigationUtil } from '@reown/appkit-common'

@customElement('w3m-smart-session-created-view')
export class W3mSmartSessionCreatedView extends LitElement {
public static override styles = styles

// -- Render -------------------------------------------- //
public override render() {
return html`
<wui-flex
flexDirection="column"
alignItems="center"
gap="xxl"
.padding=${['0', '0', 'l', '0'] as const}
>
${this.onboardingTemplate()}
<wui-link
@click=${() => {
CoreHelperUtil.openHref(NavigationUtil.URLS.FAQ, '_blank')
}}
>
What's a Smart Session?
</wui-link>
${this.buttonsTemplate()}
</wui-flex>
`
}

// -- Private ------------------------------------------- //
private onboardingTemplate() {
return html` <wui-flex
flexDirection="column"
gap="xxl"
alignItems="center"
.padding=${['0', 'xxl', '0', 'xxl'] as const}
>
<wui-flex gap="s" alignItems="center" justifyContent="center">
<wui-icon-box
size="xl"
iconcolor="fg-100"
backgroundcolor="inverse-100"
icon="clock"
background="opaque"
></wui-icon-box>
</wui-flex>
<wui-flex flexDirection="column" alignItems="center" gap="s">
<wui-text align="center" variant="medium-600" color="fg-100">
Smart Session created successfully
</wui-text>
<wui-text align="center" variant="paragraph-400" color="fg-100">
You can manage your session from your account settings.
</wui-text>
</wui-flex>
</wui-flex>`
}

private buttonsTemplate() {
return html`<wui-flex
.padding=${['0', '2l', '0', '2l'] as const}
gap="s"
class="continue-button-container"
>
<wui-button fullWidth size="lg" borderRadius="xs" @click=${this.redirectToAccount.bind(this)}>
Got it!
</wui-button>
</wui-flex>`
}

private redirectToAccount() {
RouterController.replace('Account')
}
}

declare global {
interface HTMLElementTagNameMap {
'w3m-smart-session-created-view': W3mSmartSessionCreatedView
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { css } from 'lit'

export default css`
.continue-button-container {
width: 100%;
}
`
2 changes: 2 additions & 0 deletions packages/scaffold-ui/src/modal/w3m-router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ export class W3mRouter extends LitElement {
return html`<w3m-register-account-name-view></w3m-register-account-name-view>`
case 'RegisterAccountNameSuccess':
return html`<w3m-register-account-name-success-view></w3m-register-account-name-success-view>`
case 'SmartSessionCreated':
return html`<w3m-smart-session-created-view></w3m-smart-session-created-view>`
default:
return html`<w3m-connect-view></w3m-connect-view>`
}
Expand Down
3 changes: 2 additions & 1 deletion packages/scaffold-ui/src/partials/w3m-header/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ function headings() {
: 'Connect Social',
ConnectingMultiChain: 'Select chain',
ConnectingFarcaster: 'Farcaster',
SwitchActiveChain: 'Switch chain'
SwitchActiveChain: 'Switch chain',
SmartSessionCreated: 'Session created'
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import { getW3mThemeVariables } from '@reown/appkit-common'

// -- Variables ------------------------------------------- //
const PAGE_HEIGHT = 400
const PAGE_HEIGHT = 600
const PAGE_WIDTH = 360
const HEADER_HEIGHT = 64

Expand Down Expand Up @@ -60,11 +60,15 @@ export class W3mApproveTransactionView extends LitElement {
await this.syncTheme()

this.iframe.style.display = 'block'
const container = this?.renderRoot?.querySelector('div') as HTMLDivElement
this.bodyObserver = new ResizeObserver(entries => {
const contentBoxSize = entries?.[0]?.contentBoxSize
const width = contentBoxSize?.[0]?.inlineSize

this.iframe.style.height = `${PAGE_HEIGHT}px`

// Update container size to prevent the iframe from being cut off
container.style.height = `${PAGE_HEIGHT}px`
if (width && width <= 430) {
this.iframe.style.width = '100%'
this.iframe.style.left = '0px'
Expand All @@ -84,7 +88,7 @@ export class W3mApproveTransactionView extends LitElement {

// -- Render -------------------------------------------- //
public override render() {
return html`<div data-ready=${this.ready}></div>`
return html`<div data-ready=${this.ready} id="w3m-frame-container"></div>`
}

// -- Private ------------------------------------------- //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { css } from 'lit'
export default css`
div {
width: 100%;
height: 400px;
}
[data-ready='false'] {
Expand Down
1 change: 1 addition & 0 deletions packages/ui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export * from './src/composites/wui-select/index.js'
export * from './src/layout/wui-flex/index.js'
export * from './src/layout/wui-grid/index.js'
export * from './src/layout/wui-separator/index.js'
export * from './src/utils/JSXTypeUtil.js'

export { MathUtil } from './src/utils/MathUtil.js'
export { initializeTheming, setColorTheme, setThemeVariables } from './src/utils/ThemeUtil.js'
Expand Down
6 changes: 6 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit bbc48bc

Please sign in to comment.