Skip to content

Commit

Permalink
feat: add bitcoin demo
Browse files Browse the repository at this point in the history
  • Loading branch information
yuche committed Jun 7, 2024
1 parent 802461c commit f36e008
Show file tree
Hide file tree
Showing 28 changed files with 3,223 additions and 50 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
node_modules
dist

# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local
21 changes: 21 additions & 0 deletions examples/bitcoin-demo/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint", "solid"],
"extends": [
"eslint:recommended",
"plugin:solid/typescript",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended"
],
"rules": {
"prettier/prettier": [ "error", { "endOfLine" : "auto", "singleQuote": true, "semi": false } ],
"@typescript-eslint/no-unused-vars": [
"warn", // or "error"
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_",
"caughtErrorsIgnorePattern": "^_"
}
]
}
}
41 changes: 41 additions & 0 deletions examples/bitcoin-demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
## Usage

Those templates dependencies are maintained via [pnpm](https://pnpm.io) via `pnpm up -Lri`.

This is the reason you see a `pnpm-lock.yaml`. That being said, any package manager will work. This file can be safely be removed once you clone a template.

```bash
$ npm install # or pnpm install or yarn install
```

## Exploring the template

This template's goal is to showcase the routing features of Solid.
It also showcase how the router and Suspense work together to parallelize data fetching tied to a route via the `.data.ts` pattern.

You can learn more about it on the [`@solidjs/router` repository](https://github.com/solidjs/solid-router)

### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs)

## Available Scripts

In the project directory, you can run:

### `npm dev` or `npm start`

Runs the app in the development mode.<br>
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.

The page will reload if you make edits.<br>

### `npm run build`

Builds the app for production to the `dist` folder.<br>
It correctly bundles Solid in production mode and optimizes the build for the best performance.

The build is minified and the filenames include the hashes.<br>
Your app is ready to be deployed!

## Deployment

You can deploy the `dist` folder to any static host provider (netlify, surge, now, etc.)
16 changes: 16 additions & 0 deletions examples/bitcoin-demo/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link rel="icon" href="https://fav.farm/🆔" />
<title>JoyID Bitcoin Demo</title>
</head>
<body>
<noscript>You need to enable Java Script to run this app.</noscript>
<div id="root"></div>

<script src="/src/index.tsx" type="module"></script>
</body>
</html>
47 changes: 47 additions & 0 deletions examples/bitcoin-demo/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "joyid-bitcoin-demo",
"version": "0.0.0",
"description": "",
"scripts": {
"dev": "vite",
"build": "vite build",
"serve": "vite preview"
},
"license": "MIT",
"devDependencies": {
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
"@typescript-eslint/eslint-plugin": "^5.59.0",
"@typescript-eslint/parser": "^5.59.0",
"autoprefixer": "^10.4.14",
"cross-fetch": "^3.1.5",
"eslint": "^8.38.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-solid": "^0.12.1",
"postcss": "^8.4.22",
"prettier": "^2.8.7",
"rollup-plugin-node-polyfills": "^0.2.1",
"tailwindcss": "^3.3.1",
"typescript": "5",
"vite-plugin-node-polyfills": "^0.8.1",
"vite-plugin-solid": "^2.5.0",
"vite-plugin-top-level-await": "^1.4.1",
"vite-plugin-wasm": "3.2.2"
},
"dependencies": {
"@babel/runtime": "^7.24.0",
"@joyid/bitcoin": "workspace:*",
"@rgbpp-sdk/btc": "0.0.0-snap-20240329095255",
"@rgbpp-sdk/service": "0.0.0-snap-20240329095255",
"@solid-primitives/clipboard": "^1.5.4",
"@solid-primitives/storage": "^2.1.1",
"@solidjs/router": "0.8.2",
"@tanstack/solid-query": "^4.29.1",
"@unisat/wallet-sdk": "^1.3.0",
"crypto-browserify": "^3.12.0",
"daisyui": "^2.51.5",
"solid-js": "1.7.3",
"solid-toast": "^0.5.0",
"stream-browserify": "^3.0.0"
}
}
8 changes: 8 additions & 0 deletions examples/bitcoin-demo/postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// @ts-expect
// eslint-disable-next-line no-undef
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
36 changes: 36 additions & 0 deletions examples/bitcoin-demo/src/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Component, createEffect } from 'solid-js'
import { useRoutes } from '@solidjs/router'
import { Toaster } from 'solid-toast'
import { QueryClient, QueryClientProvider } from '@tanstack/solid-query'
import { routes } from './routes'
import { initConfig } from '@joyid/bitcoin'
import { useAuthData } from './hooks/localStorage'
import { JOY_ID_URL } from './env'

const qc = new QueryClient()

const App: Component = () => {
const Route = useRoutes(routes)
const { authData } = useAuthData()
createEffect(() => {
initConfig({
name: 'JoyID Bitcoin demo',
logo: 'https://fav.farm/🆔',
// optional
joyidAppURL: JOY_ID_URL,
requestAddressType: authData.addressType || 'auto',
})
})
return (
<>
<Toaster />
<QueryClientProvider client={qc}>
<main class="h-100vh w-100% max-w-500px p-5">
<Route />
</main>
</QueryClientProvider>
</>
)
}

export default App
1 change: 1 addition & 0 deletions examples/bitcoin-demo/src/constant/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const DEFAULT_SEND_ADDRESS = 'tb1qm25yz3gzk6g77wzkwmuaykqwpf2tq7g904h4sn'
11 changes: 11 additions & 0 deletions examples/bitcoin-demo/src/env/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const JOY_ID_URL =
import.meta.env.VITE_APP_JOY_ID_URL ??
'https://joyid-app-git-btc-nervina.vercel.app'

export const BTC_SERVICE_URL =
import.meta.env.VITE_APP_BTC_SERVICE_URL ??
'https://btc-assets-api.testnet.mibao.pro'

export const BTC_SERVER_TOKEN = import.meta.env.VITE_APP_BTC_SERVER_TOKEN ?? ''

export const MIN_UTXO_AMOUNT = 10000
8 changes: 8 additions & 0 deletions examples/bitcoin-demo/src/errors/404.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default function NotFound() {
return (
<section class="p-8">
<h1 class="text-2xl font-bold">404: Not Found</h1>
<p class="mt-4">It's gone 😞</p>
</section>
)
}
8 changes: 8 additions & 0 deletions examples/bitcoin-demo/src/global.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

#root {
display: flex;
justify-content: center;
}
49 changes: 49 additions & 0 deletions examples/bitcoin-demo/src/hooks/localStorage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { createEffect } from 'solid-js'
import { createStore, produce, SetStoreFunction, Store } from 'solid-js/store'
import { JOY_ID_URL } from '../env'

export function createLocalStore<T extends object>(
name: string,
init: T
): [Store<T>, SetStoreFunction<T>] {
const localState = localStorage.getItem(name)
const [state, setState] = createStore<T>(
localState ? JSON.parse(localState) : init
)
createEffect(() => {
localStorage.setItem(name, JSON.stringify(state))
})
return [state, setState]
}

export const EMPTY_OBJECT = Object.create(null)

export const storageKey = `demo:auth-data:${JOY_ID_URL}`

const [authData, setAuthData] = createLocalStore<{
address: string
pubkey: string
mode: 'popup' | 'redirect'
addressType: 'p2tr' | 'p2wpkh' | 'auto'
}>(storageKey, EMPTY_OBJECT)

export function useAuthData() {
const isAuthcated = Object.keys(authData).length > 0
return { authData, setAuthData, isAuthcated }
}

export function useLogout() {
return () => {
setAuthData(
produce((s) => {
for (const k in s) {
if (Object.prototype.hasOwnProperty.call(s, k)) {
// @ts-ignore
s[k] = undefined
}
}
})
)
}
}
11 changes: 11 additions & 0 deletions examples/bitcoin-demo/src/hooks/service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { DataSource } from '@rgbpp-sdk/btc'
import { BtcAssetsApi } from '@rgbpp-sdk/service'
import { BTC_SERVICE_URL, BTC_SERVER_TOKEN } from '../env'
export { sendBtc } from '@rgbpp-sdk/btc'

export const btcService = BtcAssetsApi.fromToken(
BTC_SERVICE_URL,
BTC_SERVER_TOKEN
)

export const btcDataSource = new DataSource(btcService, 1)
65 changes: 65 additions & 0 deletions examples/bitcoin-demo/src/hooks/useSendSuccessToast.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import toast from 'solid-toast'

export const useSendSuccessToast = () => {
return (txHash: string) => {
toast.custom(
(t) => {
return (
<div class="alert alert-success shadow-lg max-w-md">
<div>
<svg
xmlns="http://www.w3.org/2000/svg"
class="stroke-current flex-shrink-0 h-6 w-6"
fill="none"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<div class="flex-col flex">
<span>Transaction Sent. View on:</span>
<a
class="link break-all"
href={`https://mempool.space/testnet/tx/${txHash}`}
target="_blank"
>
{txHash}
</a>
</div>
<div class="flex-none">
<button
class="btn btn-circle btn-outline btn-error btn-xs"
onClick={() => toast.dismiss(t.id)}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</div>
</div>
</div>
)
},
{
position: 'bottom-center',
duration: 10000,
unmountDelay: 0,
}
)
}
}
24 changes: 24 additions & 0 deletions examples/bitcoin-demo/src/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* @refresh reload */
import './global.css'

import { render } from 'solid-js/web'
import { Router } from '@solidjs/router'

import App from './app'

const root = document.getElementById('root')

if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
throw new Error(
'Root element not found. Did you forget to add it to your index.html? Or maybe the id attribute got mispelled?'
)
}

render(
() => (
<Router>
<App />
</Router>
),
root as HTMLElement
)
Loading

0 comments on commit f36e008

Please sign in to comment.