Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Introduction and CKB Guides. #28

Merged
merged 11 commits into from
Jan 15, 2024
69 changes: 69 additions & 0 deletions components/click-to-activate/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { useState } from 'react'

export function ClickToActivate({ children }: React.PropsWithChildren<any>)
{
const [active, setActive] = useState(false);
const [buttonHover, setButtonHover] = useState(false);
const [buttonActive, setButtonActive] = useState(false);

let html;
if(!active)
{
const divStyle =
{
background: "#f2f7fc",
border: "1px solid transparent",
borderRadius: "10px",
height: "500px",
marginTop: "20px",
width: "100%",
};
const buttonStyle =
{
background: "white",
border: "2px solid black",
borderRadius: "10px",
cursor: "pointer",
display: "block",
fontSize: "30px",
margin: "225px auto 0 auto",
padding: "10px",
};
const buttonStyleHover =
{
...buttonStyle,
border: "2px solid #006be6",
color: "#006be6",
}
const buttonStyleActive =
{
...buttonStyle,
background: "#006be6",
color: "white",
}
let currentButtonStyle = buttonStyle;
if(buttonHover) currentButtonStyle = buttonStyleHover;
if(buttonActive) currentButtonStyle = buttonStyleActive;

html =
(
<div className="click-to-activate" style={divStyle}>
<button
className="click-to-activate-button"
onClick={()=>setActive(true)}
onMouseOver={()=>setButtonHover(true)}
onMouseOut={()=>{setButtonHover(false);setButtonActive(false);}}
onMouseDown={()=>setButtonActive(true)}
onMouseUp={()=>setButtonActive(false)}
style={currentButtonStyle}>
Click to Activate Demo
</button>
</div>
);
}
else
{
html = children;
}
return html;
}
10 changes: 10 additions & 0 deletions pages/guide/ckb/_shared/callout-challenge-vs-message.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Callout } from 'nextra/components';

<Callout emoji="ℹ️" type="info">
Understanding the difference between a `challenge` and a `message`.

A `challenge` is what you as a developer need JoyID to sign.
A `message` is the piece of data that JoyID actually signs. A `message` is a combination of a `challenge` and some other data needed to complete the process, such as authenticator data, etc. The `challenge` is always included within the `message`.

For more information, you can check out the [WebAuthn Spec](https://www.w3.org/TR/webauthn-2/#sctn-op-get-assertion).
</Callout>
1 change: 1 addition & 0 deletions pages/guide/ckb/_shared/note-code-does-not-broadcast.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Note: The code below will create a signed transaction, but it does not broadcast it to the network. To do so you must use an RPC call to a CKB node. For more information on setting up a local node or using a public community node, please visit the [Nervos Docs Site](https://docs.nervos.org/).
69 changes: 69 additions & 0 deletions pages/guide/ckb/_shared/step-1-save-users-joyid-info.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { FrameworkTabs } from '@/components/framework-tabs';

## Step 1: Save the User's JoyID Information

In the [connect guide](/guide/ckb/connect), we established a connection with JoyID and obtained the user's JoyID information. It's essential to retain this information so it can be used in the signing process later on. There are many ways this can be done. Below, we demonstrate two common methods: using a state variable in a React component and employing the Vuex store in a Vue app.

<FrameworkTabs>
<FrameworkTabs.React>
```ts filename="App.tsx" /connect/
import * as React from 'react';
import { connect } from '@joyid/ckb';
import './style.css';

export default function App() {
const [joyidInfo, setJoyidInfo] = React.useState(null);

const onConnect = async () => {
try {
const authData = await connect();
setJoyidInfo(authData);
console.log(`JoyID user info:`, authData);
} catch (error) {
console.error(error);
}
}

return (
<div>
<h1>Hello JoyID!</h1>
<button onClick={onConnect}>Connect JoyID</button>
</div>
);
}
```
</FrameworkTabs.React>
<FrameworkTabs.Vue>
```vue filename="App.vue" /connect/
<template>
<div id="app">
<h1>Hello JoyID!</h1>
<button @click="connect">Connect JoyID</button>
</div>
</template>

<script>
import { connect } from '@joyid/ckb';

export default {
name: 'App',
data() {
return {
joyidInfo: null,
}
},
methods: {
async connect() {
try {
const authData = await connect();
this.joyidInfo = authData;
console.log(`JoyID user info:`, authData);
} catch (error) {
console.error(error);
}
},
},
}
```
</FrameworkTabs.Vue>
</FrameworkTabs>
116 changes: 65 additions & 51 deletions pages/guide/ckb/connect.mdx
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import { Callout } from 'nextra/components';
import { ClickToActivate } from '@/components/click-to-activate';
import { FrameworkTabs } from '@/components/framework-tabs';

# Connect

Connect your dapp with the JoyID which enables your dapp to interact with its users' Nervos CKB accounts. Nervos CKB is a public permissionless blockchain and the layer 1 of Nervos. See [Nervos Docs ↗](https://docs.nervos.org/) for more details.
In this guide, we will use the `@joyid/ckb` SDK `connect()` function to connect a dapp to the JoyID wallet and Nervos CKB network.

In this integration guide, we will use `@joyid/ckb` SDK to connect to JoyID wallet with Nervos CKB network.
Connecting your dapp to JoyID is always the first step before you can interact with a user's Nervos CKB address. This step must be completed before any other actions can be performed.

## Initialization
Nervos CKB is a layer 1 public blockchain and the foundation of the Nervos Network ecosystem. For more information, please visit the [Nervos Docs](https://docs.nervos.org/) website.

Before writing business code, you can call the initialization function `initConfig` on the project entry:
## Initialization

import { FrameworkTabs } from '@/components/framework-tabs'
You must always initialize the configuration as the first step. This is done using the `initConfig()` function and is normally done immediately after program entry.

<FrameworkTabs>
<FrameworkTabs.React>
<FrameworkTabs.React>
```ts filename="main.tsx" /initConfig/
import React from "react";
import ReactDOM from "react-dom/client";
Expand All @@ -30,16 +34,16 @@ ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<App />
</React.StrictMode>,
);

```
</FrameworkTabs.React>
<FrameworkTabs.Vue>
</FrameworkTabs.React>
<FrameworkTabs.Vue>
```ts filename="main.ts" /initConfig/
import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
import { initConfig } from "@joyid/ckb";
import App from "./App.vue";
import "./style.css";

// Initialize JoyID configuration.
initConfig({
name: "JoyID demo",
logo: "https://fav.farm/🆔",
Expand All @@ -48,33 +52,30 @@ initConfig({

createApp(App).mount("#app");
```

</FrameworkTabs.Vue>
</FrameworkTabs.Vue>
</FrameworkTabs>


### Get Started

Let's start the journey of business code programming. Suppose you have the following code:

With the configuration initialized, we're ready to begin adding code to interact with JoyID. Next we add some basic interface code.

<FrameworkTabs>
<FrameworkTabs.React>
<FrameworkTabs.React>
```ts filename="App.tsx"
import * as React from 'react'
import './style.css'
import * as React from 'react';
import './style.css';

export default function App() {
return (
<div>
<h1>Hello JoyID!</h1>
</div>
)
);
}

```
</FrameworkTabs.React>
<FrameworkTabs.Vue>
</FrameworkTabs.React>
<FrameworkTabs.Vue>
```vue filename="App.vue"
<template>
<div id="app">
Expand All @@ -88,27 +89,25 @@ export default {
}
</script>
```

</FrameworkTabs.Vue>
</FrameworkTabs.Vue>
</FrameworkTabs>


To connect with JoyID, we just need to add a `button` element and listen to the `onClick` event:
To connect with JoyID, we will add to our interface a `button`, and bind the `onClick` event to call the `connect()` function.

<FrameworkTabs>
<FrameworkTabs.React>
<FrameworkTabs.React>
```ts filename="App.tsx" /connect/
import * as React from 'react'
import { connect } from '@joyid/ckb'
import './style.css'
import * as React from 'react';
import { connect } from '@joyid/ckb';
import './style.css';

export default function App() {
const onConnect = async () => {
try {
const authData = await connect()
console.log(`JoyID user info:`, authData)
const authData = await connect();
console.log(`JoyID user info:`, authData);
} catch (error) {
console.log(error)
console.error(error);
}
}

Expand All @@ -117,11 +116,11 @@ export default function App() {
<h1>Hello JoyID!</h1>
<button onClick={onConnect}>Connect JoyID</button>
</div>
)
);
}
```
</FrameworkTabs.React>
<FrameworkTabs.Vue>
</FrameworkTabs.React>
<FrameworkTabs.Vue>
```vue filename="App.vue" /connect/
<template>
<div id="app">
Expand All @@ -131,33 +130,48 @@ export default function App() {
</template>

<script>
import { connect } from '@joyid/ckb'
import { connect } from '@joyid/ckb';

export default {
name: 'App',
methods: {
async connect() {
try {
const authData = await connect()
console.log(`JoyID user info:`, authData)
const authData = await connect();
console.log(`JoyID user info:`, authData);
} catch (error) {
console.log(error)
console.error(error);
}
},
},
}
</script>
```

</FrameworkTabs.Vue>
</FrameworkTabs.Vue>
</FrameworkTabs>

## Try it out
After establishing a connection, the `connect()` function will return the user's JoyID information.

<FrameworkTabs>
<FrameworkTabs.React>
<iframe className="sandbox" src="https://stackblitz.com/edit/react-joyid-ckb-connect?embed=1&file=App.tsx&view=preview" />
</FrameworkTabs.React>
<FrameworkTabs.Vue>
<iframe className="sandbox" src="https://stackblitz.com/edit/vue-joyid-ckb-connect?embed=1&file=App.vue&view=preview" />
</FrameworkTabs.Vue>
</FrameworkTabs>
```json
{
"address": "ckt1qrfrwcdnvssswdwpn3s9v8fp87emat306ctjwsm3nmlkjg8qyza2cqgqqx0r8ye9e2hqd7sc9wpxxvlul6ynzltyvqftele3",
"ethAddress": "0x2b0586bf591CA8e96132646BD17bc86DaDc6D015",
"keyType": "main_key",
"alg": -7,
"nostrPubkey": "399669b4c1802f42e4515104c7b7bcb7d1385ccc0547906cb6d5a8d0cb8d5575",
"pubkey": "755a1bfa644d55a5914d185ea27c1f67565ccef677fbbb4750551d33f3789e89898a455599164ca2293bef50d2f5424bf97209e661a1e2f636d8e782340ccf15"
}
```

## Try it Out

<ClickToActivate>
<FrameworkTabs>
<FrameworkTabs.React>
<iframe className="sandbox" src="https://stackblitz.com/edit/react-joyid-ckb-connect-hc3kwc?embed=1&file=src%2FApp.tsx&view=preview" />
</FrameworkTabs.React>
<FrameworkTabs.Vue>
<iframe className="sandbox" src="https://stackblitz.com/edit/vue-joyid-ckb-connect-tnr3yj?embed=1&file=src%2FApp.vue&view=preview" />
</FrameworkTabs.Vue>
</FrameworkTabs>
</ClickToActivate>
Loading