Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/origin/develop' into joyid
Browse files Browse the repository at this point in the history
# Conflicts:
#	examples/pnpm-lock.yaml
  • Loading branch information
homura committed Apr 29, 2024
2 parents 08e22ca + ff0b583 commit 16b32a7
Show file tree
Hide file tree
Showing 20 changed files with 1,744 additions and 532 deletions.
22 changes: 16 additions & 6 deletions .eslintrc.next.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,25 @@ module.exports = {
tsconfigRootDir: __dirname,
project: ["./tsconfig.json", "packages/*/tsconfig.json"],
},
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
rules: {
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/explicit-module-boundary-types": "error",
"no-constant-condition": ["error", { "checkLoops": false }]
}
"no-constant-condition": ["error", { checkLoops: false }],
"@typescript-eslint/no-magic-numbers": [
"error",
{
ignoreEnums: true,
ignoreArrayIndexes: true,
ignore: [
-1, // index -1 is not found
0, // first element of an array
1, // common for i + 1 in a loop
16, // toString(16)
],
},
],
},
},
],
};
3 changes: 3 additions & 0 deletions examples/omni-lock-metamask/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,8 @@
"@types/react-dom": "^18.0.9",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"devDependencies": {
"parcel": "^2.9.5"
}
}
21 changes: 21 additions & 0 deletions examples/omni-lock-solana/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Lumos Works with Solana

Nervos maintains a powerful lock
called [Omnilock](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0042-omnilock/0042-omnilock.md) (previously named RC lock), which
can use Phantom as a signer. This example will show how to use Lumos to send a transaction using Omnilock and Phantom

## Quick Start

> we should [build](..) Lumos project first before we start this example
```
npm run build
cd examples/omni-lock-solana
npm start
```

## Links

- [Phantom](https://phantom.app/) - A crypto wallet for Solana
- [Nervos Faucet](https://faucet.nervos.org/) - Claim Nervos testnet CKB
- [Omnilock](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0042-omnilock/0042-omnilock.md) - Omnilock intro
13 changes: 13 additions & 0 deletions examples/omni-lock-solana/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" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lumos ❤️ Solana & Phantom</title>
</head>
<body>
<div id="root"></div>
<script src="index.tsx" type="module"></script>
</body>
</html>
93 changes: 93 additions & 0 deletions examples/omni-lock-solana/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import React, { useEffect, useState } from "react";
import { helpers, Script, config, commons } from "@ckb-lumos/lumos";
import ReactDOM from "react-dom";
import { asyncSleep, capacityOf, solana, transfer } from "./lib";

const App: React.FC = () => {
const [solanaAddr, setSolanaAddr] = useState("");
const [omniAddr, setOmniAddr] = useState("");
const [omniLock, setOmniLock] = useState<Script>();
const [balance, setBalance] = useState("-");

const [transferAddr, setTransferAddress] = useState("");
const [transferAmount, setTransferAmount] = useState("");

const [isSendingTx, setIsSendingTx] = useState(false);
const [txHash, setTxHash] = useState("");

useEffect(() => {
asyncSleep(300).then(() => {
if (solana) connectToWallet();
});
}, []);

function connectToWallet() {
solana
.connect()
.then(({ publicKey }) => {
const solanaAddr = publicKey.toBase58();
const omniLockScript = commons.omnilock.createOmnilockScript({
auth: { flag: "SOLANA", content: solanaAddr },
});

const omniAddr = helpers.encodeToAddress(omniLockScript);

setSolanaAddr(solanaAddr);
setOmniAddr(omniAddr);
setOmniLock(omniLockScript);

return omniAddr;
})
.then((omniAddr) => capacityOf(omniAddr))
.then((balance) => setBalance(balance.div(10 ** 8).toString() + " CKB"));
}

function onTransfer() {
if (isSendingTx) return;
setIsSendingTx(true);

transfer({ amount: transferAmount, from: omniAddr, to: transferAddr })
.then(setTxHash)
.catch((e) => {
console.log(e);
alert(e.message || JSON.stringify(e));
})
.finally(() => setIsSendingTx(false));
}

if (!solana) return <div>Phantom is not installed</div>;
if (!solanaAddr) return <button onClick={connectToWallet}>Connect to Phantom</button>;

return (
<div>
<ul>
<li>Solana Address: {solanaAddr}</li>
<li>Nervos Address(Omni): {omniAddr}</li>
<li>
Current Omni lock script:
<pre>{JSON.stringify(omniLock, null, 2)}</pre>
</li>

<li>Balance: {balance}</li>
</ul>

<div>
<h2>Transfer to</h2>
<label htmlFor="address">Address</label>&nbsp;
<input id="address" type="text" onChange={(e) => setTransferAddress(e.target.value)} placeholder="ckt1..." />
<br />
<label htmlFor="amount">Amount</label>
&nbsp;
<input id="amount" type="text" onChange={(e) => setTransferAmount(e.target.value)} placeholder="shannon" />
<br />
<button onClick={onTransfer} disabled={isSendingTx}>
Transfer
</button>
<p>Tx Hash: {txHash}</p>
</div>
</div>
);
};

const app = document.getElementById("root");
ReactDOM.render(<App />, app);
71 changes: 71 additions & 0 deletions examples/omni-lock-solana/lib.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { BI, helpers, Indexer, RPC, config, commons } from "@ckb-lumos/lumos";
import { common, omnilock } from "@ckb-lumos/lumos/common-scripts";
import { blockchain, bytify, hexify } from "@ckb-lumos/lumos/codec";
import { Config } from "@ckb-lumos/lumos/config";

const CKB_RPC_URL = "https://testnet.ckb.dev";
const rpc = new RPC(CKB_RPC_URL);
const indexer = new Indexer(CKB_RPC_URL);

export const CONFIG: Config = config.TESTNET;

config.initializeConfig(CONFIG);

declare global {
interface Window {
phantom: {
solana: omnilock.solana.Provider;
};
}
}

export const solana = window.phantom.solana;

export function asyncSleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}

interface Options {
from: string;
to: string;
amount: string;
}

export async function transfer(options: Options): Promise<string> {
let txSkeleton = helpers.TransactionSkeleton({ cellProvider: indexer });

txSkeleton = await common.transfer(txSkeleton, [options.from], options.to, options.amount);
txSkeleton = await common.payFeeByFeeRate(txSkeleton, [options.from], 1000);
txSkeleton = commons.omnilock.prepareSigningEntries(txSkeleton);

const signedMessage = await omnilock.solana.signMessage(
txSkeleton.signingEntries.get(0)!.message,
window.phantom.solana
);

const signedWitness = hexify(
blockchain.WitnessArgs.pack({
lock: commons.omnilock.OmnilockWitnessLock.pack({ signature: bytify(signedMessage) }),
})
);

txSkeleton = txSkeleton.update("witnesses", (witnesses) => witnesses.set(0, signedWitness));

const signedTx = helpers.createTransactionFromSkeleton(txSkeleton);
const txHash = await rpc.sendTransaction(signedTx, "passthrough");

return txHash;
}

export async function capacityOf(address: string): Promise<BI> {
const collector = indexer.collector({
lock: helpers.parseAddress(address),
});

let balance = BI.from(0);
for await (const cell of collector.collect()) {
balance = balance.add(cell.cellOutput.capacity);
}

return balance;
}
22 changes: 22 additions & 0 deletions examples/omni-lock-solana/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"private": true,
"name": "@lumos-examples/omni-lock-solana",
"description": "",
"scripts": {
"start": "parcel index.html",
"lint": "tsc --noEmit"
},
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
"@ckb-lumos/lumos": "canary",
"@types/react": "^18.0.25",
"@types/react-dom": "^18.0.9",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"devDependencies": {
"parcel": "^2.9.3"
}
}
9 changes: 9 additions & 0 deletions examples/omni-lock-solana/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"compilerOptions": {
"lib": ["dom"],
"jsx": "react",
"module": "CommonJS",
"skipLibCheck": true,
"esModuleInterop": true
}
}
Loading

1 comment on commit 16b32a7

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 New canary release: 0.22.2

npm install @ckb-lumos/[email protected]

Please sign in to comment.