Skip to content

Commit

Permalink
feat: scaffold
Browse files Browse the repository at this point in the history
  • Loading branch information
sonhavietnamese committed Aug 3, 2024
0 parents commit 27250ba
Show file tree
Hide file tree
Showing 33 changed files with 825 additions and 0 deletions.
11 changes: 11 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
VITE_OIDC_CLIENT_ID="8b300f32-b604-49ba-80da-c21e26e82a03"
VITE_OIDC_CALLBACK_URL="https://test-mpc-telegram-miniapp.vercel.app"
VITE_OIDC_AUTHORIZATION_ENDPOINT="https://athena.skymavis.com/oauth2/auth"
VITE_OIDC_CLIENT_SECRET="U~XhO4arIQT4oZ8K1jeCLDzqgp"
VITE_OIDC_TOKEN_ENDPOINT="https://api-gateway.skymavis.com/account/oauth2/token"

VITE_API_KEY="PAcmitDmTyC7AB9gq61RyxsYsjJ3oZ36"

VITE_CHAIN_ID="2021"

VITE_LOCKBOX_SERVICE_ENV="prod"
18 changes: 18 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
}
25 changes: 25 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
.vercel
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Pray Atia Telegram Mini App

This is a basic example of integrating a Telegram mini-app with an MPC (Multi-Party Computation) wallet. The goal is to bring more value to the game and the Ronin ecosystem.

In this example, a simple click game is implemented using the Lockbox and Mavis Account service. Both on-chain and off-chain logic are included. Every 10 clicks, the user can claim an amount of RON by calling the smart contract to claim the rewards.

![Banner](/docs/banner.png)

## About
This example using following libraries and libs:
- [ReactJs](https://react.dev/)
- [Vite](https://vitejs.dev/)
- [Bun](https://bun.sh/)
- [Lockbox](https://docs.skymavis.com/mavis/mpc/overview)
- [Mavis Account](https://docs.skymavis.com/mavis/mavis-account/overview)
- [Viem](https://viem.sh/)


## Quick Start

The example using some internal packages that is not public at the moment. In order to use it, send a request to be guide to install the packages.
After the request is a

```bash
git clone ...
cd ...
bun install
```

Open the browser at ...

## Breakdown

using account service
flow



## Deployment
### Prequisite

These are config that use need to prepare to launch the mini app production

- asd
-
-
-
-

## Table of Content
Binary file added bun.lockb
Binary file not shown.
Binary file added docs/banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Pray Atia Miniapp</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
39 changes: 39 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"name": "test-mpc-telegram-miniapp",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite --port 3000",
"build": "tsc -b && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"@axieinfinity/lockbox": "^2.1.5",
"@sky-mavis/mavis-id-sdk": "0.0.2",
"crypto": "^1.0.1",
"framer-motion": "^11.3.8",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"viem": "^2.17.10",
"zustand": "^4.5.4"
},
"devDependencies": {
"@types/node": "^20.14.11",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.15.0",
"@typescript-eslint/parser": "^7.15.0",
"@vitejs/plugin-react-swc": "^3.5.0",
"autoprefixer": "^10.4.19",
"eslint": "^8.57.0",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-refresh": "^0.4.7",
"postcss": "^8.4.39",
"tailwindcss": "^3.4.6",
"typescript": "^5.2.2",
"vite": "^5.3.4",
"vite-plugin-node-polyfills": "^0.22.0"
}
}
6 changes: 6 additions & 0 deletions postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
Binary file added public/btn-claim.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/btn-login.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/element-atia.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/icon-ron.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/panel-address.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/panel-count.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/puff-loading.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/vite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions src/abi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export const abi = [
{ inputs: [], stateMutability: 'payable', type: 'constructor' },
{
anonymous: false,
inputs: [
{ indexed: true, internalType: 'address', name: 'player', type: 'address' },
{ indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' },
],
name: 'RewardClaimed',
type: 'event',
},
{ inputs: [], name: 'claimReward', outputs: [], stateMutability: 'nonpayable', type: 'function' },
{
inputs: [{ internalType: 'address', name: 'player', type: 'address' }],
name: 'getScore',
outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [{ internalType: 'uint256', name: 'score', type: 'uint256' }],
name: 'setScore',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{ stateMutability: 'payable', type: 'receive' },
]
161 changes: 161 additions & 0 deletions src/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import { AnimatePresence, motion } from 'framer-motion'
import React, { useEffect, useState } from 'react'
import { MPC_STATUS, useMPCStore } from './store'
import { useMpc } from './use-mpc'

const trimAddress = (address: string) => {
return `${address.slice(0, 6)}...${address.slice(-4)}`
}

function App() {
const { isConnected, lockbox, status } = useMPCStore()
const { loginWithAS, claimReward } = useMpc()
const [address, setAddress] = useState<string | null>('')
const [balance, setBalance] = useState<number>(0)
const [count, setCount] = useState(0)

const [claimable, setClaimable] = useState(false)
const [isClaiming, setIsClaiming] = useState(false)

const fetchInfo = async () => {
if (!lockbox || !isConnected) return

const addresses = await lockbox.getProvider().request<string[]>({ method: 'eth_accounts' })
const balances = await lockbox.getProvider().request<string>({ method: 'eth_getBalance', params: [addresses[0] as `0x${string}`, 'latest'] })

setAddress(addresses[0])
setBalance(Number((Number(balances) / 1e18).toFixed(2)))
}

const login = async () => {
loginWithAS()
}

useEffect(() => {
fetchInfo()
}, [lockbox, isConnected])

useEffect(() => {
if (address && count > 1 && count % 10 === 0) {
setClaimable(true)
}
}, [count])

const claim = async () => {
setIsClaiming(true)

try {
await claimReward()
setBalance((prev) => prev + 0.5)
} catch (error) {
console.log('Error claiming reward', error)
}

setIsClaiming(false)
setClaimable(false)
}

const pray = () => {
setCount((prev) => prev + 1)
}

return (
<main className='w-screen overflow-hidden relative h-screen flex items-center justify-center'>
<div className='pointer-events-none absolute top-0 left-0 z-10 h-screen w-screen bg-vignette' />
<div className='bg-[url("./assets/background.png")] w-full h-full bg-center bg-cover absolute inset-0' />

<AnimatePresence>
{claimable ? <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className='overlay' /> : null}
</AnimatePresence>

<motion.figure layoutId='atia' className='relative z-0 bottom-[80px] w-[200px] h-[200px] active:scale-95 ' onClick={pray}>
<img src='element-atia.png' alt='Atia' className='bottom-[0px]' />
</motion.figure>

<AnimatePresence mode='wait'>
{claimable && (
<motion.div
layout
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0, transition: { duration: 0.05 } }}
className=' absolute z-20 bg-[#91582A] w-[350px] h-[480px] rounded-2xl border-[#362D1B] border-2 flex items-center flex-col'>
<motion.figure layoutId='atia' className='w-[200px] h-[200px] active:scale-95 mt-4' onClick={pray}>
<img src='element-atia.png' alt='Atia' className='bottom-[0px]' />
</motion.figure>

<motion.span
layout
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0, transition: { duration: 0.05 } }}
className='text-[#F7DAB2] text-xl mt-7'>
Atia Bless you
</motion.span>

<motion.div
layout
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0, transition: { duration: 0.05 } }}
className='flex gap-2 items-center mr-5 justify-center mt-5'>
<img src='icon-ron.png' alt='image' className='w-12 h-12' />
<span className='text-[#F7DAB2] text-[40px]'>0.5</span>
</motion.div>

{isClaiming ? (
<motion.img src='puff-loading.png' className='h-[80px] animate-spin w-auto mt-7' />
) : (
<motion.img
layout
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0, transition: { duration: 0.05 } }}
src='btn-claim.png'
alt='login'
className='h-[60px] w-auto mt-10'
onClick={claim}
/>
)}
</motion.div>
)}
</AnimatePresence>

<div />
{address && (
<div className='absolute z-10 top-10 h-[50px]'>
<div className='relative h-[70px]'>
<img src='panel-count.png' alt='login' className='h-full w-auto' />
<span className='absolute font-custom text-[#F7DAB2] left-1/2 top-1/2 -translate-x-1/2 text-3xl -translate-y-1/2'>{count}</span>
</div>
</div>
)}

<div className='absolute z-10 bottom-20 h-[60px]'>
{status === MPC_STATUS.IDLE ? (
<>
{!address ? (
<img src='btn-login.png' alt='login' className='h-full w-auto' onClick={login} />
) : (
<div className='flex flex-col gap-2'>
<div className='relative h-[60px]'>
<img src='panel-address.png' alt='login' className='h-full w-auto' />
<span className='absolute text-[#FFFABA] text-2xl left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2'>{trimAddress(address)}</span>
</div>

<div className='relative h-[60px]'>
<img src='panel-address.png' alt='login' className='h-full w-auto' />
<span className='absolute text-[#FFFABA] text-2xl left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2'>{balance} RON</span>
</div>
</div>
)}
</>
) : (
<motion.img src='puff-loading.png' className='h-[80px] animate-spin w-auto mt-7' />
)}
</div>
</main>
)
}

export default App
Binary file added src/assets/CCBackBeatRegular.ttf
Binary file not shown.
Binary file added src/assets/background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/assets/react.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 27250ba

Please sign in to comment.