Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions web-v2/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
FROM node:20-alpine AS builder
FROM rust:1.90-bookworm AS lwk-builder

ARG LWK_REF=wasm_0.16.0
ARG LWK_COMMIT=4786e456db6efc05413721f6489899a6426eaa47

RUN apt-get update && apt-get install -y --no-install-recommends \
git pkg-config libssl-dev ca-certificates clang \
&& rm -rf /var/lib/apt/lists/*
RUN rustup target add wasm32-unknown-unknown
RUN cargo install wasm-pack --locked
RUN git clone --depth 1 --branch "${LWK_REF}" https://github.com/Blockstream/lwk.git /tmp/lwk
RUN test "$(git -C /tmp/lwk rev-parse HEAD)" = "${LWK_COMMIT}"
WORKDIR /tmp/lwk/lwk_wasm
RUN RUSTFLAGS='--cfg web_sys_unstable_apis' wasm-pack build --target web --out-dir pkg_web --features simplicity,serial

FROM node:22-bookworm AS builder

WORKDIR /app
RUN corepack enable
RUN corepack enable && \
corepack prepare pnpm@10.33.0 --activate

COPY package.json pnpm-lock.yaml ./

COPY --from=lwk-builder /tmp/lwk/lwk_wasm/pkg_web /lwk_wasm/pkg_web

RUN pnpm install --frozen-lockfile

COPY . .
Expand Down
2 changes: 2 additions & 0 deletions web-v2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ Copy `.env.example` to `.env` and adjust as needed.

## Install

> To build the LWK WASM module required by this app, see [docs/HOW_TO_BUILD_LWK_WASM.md](docs/HOW_TO_BUILD_LWK_WASM.md).

```bash
pnpm install
```
Expand Down
28 changes: 28 additions & 0 deletions web-v2/docs/HOW_TO_BUILD_LWK_WASM.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# How to build lwk_wasm
Comment thread
ardier16 marked this conversation as resolved.

**Recommended — Docker (stable, no Rust on host)**

## 1. **Build lwk-builder stage:**

```bash
# run from repo root
docker build -f web-v2/Dockerfile --target lwk-builder -t lwk-builder .
```

## **2. Extract pkg_web to repo root:**

```bash
docker create --name tmp lwk-builder
docker cp tmp:/tmp/lwk/lwk_wasm/pkg_web ./pkg_web_from_docker
docker rm tmp
mkdir -p ./lwk_wasm
mv ./pkg_web_from_docker ./lwk_wasm/pkg_web
```

## **3. Install & run web-v2**:

```bash
cd web-v2
pnpm install
pnpm dev
```
1 change: 1 addition & 0 deletions web-v2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"add-icon": "tsx ./scripts/add-icon.ts"
},
"dependencies": {
"lwk_web": "file:../lwk_wasm/pkg_web",
"@heroui/react": "^3.0.4",
"@tanstack/react-query": "^5.100.10",
"react": "^19.2.6",
Expand Down
37 changes: 37 additions & 0 deletions web-v2/pnpm-lock.yaml

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

2 changes: 2 additions & 0 deletions web-v2/src/constants/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ export const env = envSchema.parse({
})

export type AppEnv = z.infer<typeof envSchema>

export type NetworkName = AppEnv['VITE_NETWORK']
44 changes: 44 additions & 0 deletions web-v2/src/lwk/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { Network, SimplicityArguments, Transaction, XOnlyPublicKey } from 'lwk_web'

import type { NetworkName } from '@/constants/env'

export type Lwk = typeof import('lwk_web')

let lwk: Lwk | null = null

export async function getLwk(): Promise<Lwk> {
if (!lwk) {
lwk = await import('lwk_web')
if (typeof lwk.default === 'function') await lwk.default()
}
return lwk
}

export function createLwkNetwork(network: NetworkName, lwk: Lwk): Network {
switch (network) {
case 'liquid':
return lwk.Network.mainnet()
case 'liquidtestnet':
return lwk.Network.testnet()
case 'regtest':
return lwk.Network.regtestDefault()
}
}

export interface PsetWithExtractTx {
extractTx(): Transaction
}

export interface CreateP2trAddressParams {
source: string
args: SimplicityArguments
internalKey: XOnlyPublicKey
network: NetworkName
}

export function createP2trAddress(lwk: Lwk, params: CreateP2trAddressParams): string {
const program = lwk.SimplicityProgram.load(params.source, params.args)
const net = createLwkNetwork(params.network, lwk)
const address = program.createP2trAddress(params.internalKey, net)
return address.toString()
}
47 changes: 46 additions & 1 deletion web-v2/src/pages/Dashboard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,48 @@
import { useLwk } from '@/providers/lwk/useLwk'

// EXAMPLE OF LWK USAGE
export default function DashboardPage() {
return <h1 className='text-3xl font-semibold'>Dashboard</h1>
const { network, isTestnet, isMainnet, isRegtest, lwkNetwork } = useLwk()

const info = lwkNetwork
? {
label: lwkNetwork.toString(),
genesisBlockHash: lwkNetwork.genesisBlockHash(),
defaultExplorerUrl: lwkNetwork.defaultExplorerUrl(),
policyAsset: lwkNetwork.policyAsset().toString(),
}
: null
Comment thread
ardier16 marked this conversation as resolved.

return (
<div className='space-y-2 p-6'>
<h1 className='text-3xl font-semibold'>Dashboard</h1>
<p>
Network: <code>{network}</code>
</p>
<p>
isTestnet: {isTestnet.toString()} / isMainnet: {isMainnet.toString()} / isRegtest:{' '}
{isRegtest.toString()}
</p>
{info && (
<dl className='space-y-1 text-sm'>
<dt className='font-medium'>LWK label</dt>
<dd>
<code>{info.label}</code>
</dd>
<dt className='font-medium'>Genesis block hash</dt>
<dd>
<code className='break-all'>{info.genesisBlockHash}</code>
</dd>
<dt className='font-medium'>Default explorer</dt>
<dd>
<code>{info.defaultExplorerUrl}</code>
</dd>
<dt className='font-medium'>Policy asset</dt>
<dd>
<code className='break-all'>{info.policyAsset}</code>
</dd>
</dl>
)}
</div>
)
}
Loading