@btc-vision/walletconnect 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +4 -0
- package/.gitattributes +2 -0
- package/.prettierrc.json +12 -0
- package/.vscode/settings.json +10 -0
- package/CONTRIBUTING.md +71 -0
- package/LICENSE +21 -0
- package/README.md +58 -0
- package/browser/WalletConnection.d.ts +17 -0
- package/browser/WalletProvider.d.ts +19 -0
- package/browser/index.d.ts +2 -0
- package/browser/index.js +2 -0
- package/browser/index.js.LICENSE.txt +13 -0
- package/build/WalletConnection.d.ts +17 -0
- package/build/WalletConnection.js +90 -0
- package/build/WalletProvider.d.ts +19 -0
- package/build/WalletProvider.js +73 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +2 -0
- package/cjs/package.json +3 -0
- package/eslint.config.js +38 -0
- package/gulpfile.js +47 -0
- package/package.json +126 -0
- package/src/WalletConnection.ts +126 -0
- package/src/WalletProvider.tsx +101 -0
- package/src/index.ts +2 -0
- package/tsconfig.base.json +27 -0
- package/tsconfig.json +16 -0
- package/tsconfig.webpack.json +22 -0
- package/webpack.config.js +83 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*! For license information please see index.js.LICENSE.txt */
|
|
2
|
+
|
|
3
|
+
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @license React
|
|
7
|
+
* react-jsx-runtime.production.min.js
|
|
8
|
+
*
|
|
9
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
10
|
+
*
|
|
11
|
+
* This source code is licensed under the MIT license found in the
|
|
12
|
+
* LICENSE file in the root directory of this source tree.
|
|
13
|
+
*/
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Network } from '@btc-vision/bitcoin';
|
|
2
|
+
import { Address, Unisat, UnisatSigner } from '@btc-vision/transaction';
|
|
3
|
+
import { JSONRpcProvider } from 'opnet';
|
|
4
|
+
export declare enum SupportedWallets {
|
|
5
|
+
OP_WALLET = "op_wallet"
|
|
6
|
+
}
|
|
7
|
+
export type Signers = UnisatSigner;
|
|
8
|
+
export type Wallets = Unisat;
|
|
9
|
+
export declare class WalletConnection {
|
|
10
|
+
signer: Signers | null;
|
|
11
|
+
connect(walletType: SupportedWallets): Promise<void>;
|
|
12
|
+
disconnect(): void;
|
|
13
|
+
getAddress(): Promise<Address>;
|
|
14
|
+
getNetwork(): Promise<Network>;
|
|
15
|
+
getProvider(): Promise<JSONRpcProvider>;
|
|
16
|
+
}
|
|
17
|
+
export default WalletConnection;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { networks } from '@btc-vision/bitcoin';
|
|
2
|
+
import { Address, UnisatChainType, UnisatSigner } from '@btc-vision/transaction';
|
|
3
|
+
import { JSONRpcProvider } from 'opnet';
|
|
4
|
+
export var SupportedWallets;
|
|
5
|
+
(function (SupportedWallets) {
|
|
6
|
+
SupportedWallets["OP_WALLET"] = "op_wallet";
|
|
7
|
+
})(SupportedWallets || (SupportedWallets = {}));
|
|
8
|
+
export class WalletConnection {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.signer = null;
|
|
11
|
+
}
|
|
12
|
+
async connect(walletType) {
|
|
13
|
+
switch (walletType) {
|
|
14
|
+
case SupportedWallets.OP_WALLET:
|
|
15
|
+
if (this.signer instanceof UnisatSigner)
|
|
16
|
+
return;
|
|
17
|
+
if (window.opnet || window.unisat) {
|
|
18
|
+
try {
|
|
19
|
+
const signer = new UnisatSigner();
|
|
20
|
+
await signer.init();
|
|
21
|
+
this.signer = signer;
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (error instanceof Error)
|
|
26
|
+
throw new Error(error.message);
|
|
27
|
+
throw new Error(`Unknown error: ${error}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
throw new Error('OP Wallet not found');
|
|
32
|
+
}
|
|
33
|
+
default:
|
|
34
|
+
throw new Error('Unsupported wallet');
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
disconnect() {
|
|
38
|
+
if (!this.signer)
|
|
39
|
+
throw new Error('Wallet not connected');
|
|
40
|
+
if (this.signer instanceof UnisatSigner)
|
|
41
|
+
this.signer.unisat.disconnect();
|
|
42
|
+
this.signer = null;
|
|
43
|
+
}
|
|
44
|
+
async getAddress() {
|
|
45
|
+
if (!this.signer)
|
|
46
|
+
throw new Error('Wallet not connected');
|
|
47
|
+
if (this.signer instanceof UnisatSigner) {
|
|
48
|
+
const publicKey = await this.signer.unisat.getPublicKey();
|
|
49
|
+
return Address.fromString(publicKey);
|
|
50
|
+
}
|
|
51
|
+
throw new Error('Unsupported wallet');
|
|
52
|
+
}
|
|
53
|
+
async getNetwork() {
|
|
54
|
+
if (!this.signer)
|
|
55
|
+
throw new Error('Wallet not connected');
|
|
56
|
+
if (this.signer instanceof UnisatSigner) {
|
|
57
|
+
const chain = await this.signer.unisat.getChain();
|
|
58
|
+
switch (chain.enum) {
|
|
59
|
+
case UnisatChainType.BITCOIN_MAINNET:
|
|
60
|
+
return networks.bitcoin;
|
|
61
|
+
case UnisatChainType.BITCOIN_TESTNET:
|
|
62
|
+
return networks.testnet;
|
|
63
|
+
case UnisatChainType.BITCOIN_REGTEST:
|
|
64
|
+
return networks.regtest;
|
|
65
|
+
default:
|
|
66
|
+
throw new Error('Unsupported network');
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
throw new Error('Unsupported wallet');
|
|
70
|
+
}
|
|
71
|
+
async getProvider() {
|
|
72
|
+
if (!this.signer)
|
|
73
|
+
throw new Error('Wallet not connected');
|
|
74
|
+
if (this.signer instanceof UnisatSigner) {
|
|
75
|
+
const network = await this.getNetwork();
|
|
76
|
+
switch (network.bech32) {
|
|
77
|
+
case networks.bitcoin.bech32:
|
|
78
|
+
return new JSONRpcProvider('https://api.opnet.org', networks.bitcoin);
|
|
79
|
+
case networks.testnet.bech32:
|
|
80
|
+
return new JSONRpcProvider('https://testnet.opnet.org', networks.testnet);
|
|
81
|
+
case networks.regtest.bech32:
|
|
82
|
+
return new JSONRpcProvider('https://regtest.opnet.org', networks.regtest);
|
|
83
|
+
default:
|
|
84
|
+
throw new Error('Unsupported network');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
throw new Error('Unsupported wallet');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
export default WalletConnection;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Network } from '@btc-vision/bitcoin';
|
|
2
|
+
import { Address } from '@btc-vision/transaction';
|
|
3
|
+
import { JSONRpcProvider } from 'opnet';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { Signers, SupportedWallets } from './WalletConnection';
|
|
6
|
+
interface WalletContextType {
|
|
7
|
+
connect: (walletType: SupportedWallets) => Promise<void>;
|
|
8
|
+
disconnect: () => void;
|
|
9
|
+
address: Address | null;
|
|
10
|
+
signer: Signers | null;
|
|
11
|
+
network: Network | null;
|
|
12
|
+
provider: JSONRpcProvider | null;
|
|
13
|
+
isConnected: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare const WalletProvider: React.FC<{
|
|
16
|
+
children: React.ReactNode;
|
|
17
|
+
}>;
|
|
18
|
+
export declare const useWallet: () => WalletContextType;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { UnisatSigner } from '@btc-vision/transaction';
|
|
3
|
+
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
|
|
4
|
+
import WalletConnection from './WalletConnection';
|
|
5
|
+
const WalletContext = createContext(undefined);
|
|
6
|
+
export const WalletProvider = ({ children }) => {
|
|
7
|
+
const [walletConnection] = useState(new WalletConnection());
|
|
8
|
+
const [address, setAddress] = useState(null);
|
|
9
|
+
const [signer, setSigner] = useState(null);
|
|
10
|
+
const [network, setNetwork] = useState(null);
|
|
11
|
+
const [provider, setProvider] = useState(null);
|
|
12
|
+
const [isConnected, setIsConnected] = useState(false);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
const storedWalletType = localStorage.getItem('walletType');
|
|
15
|
+
if (storedWalletType) {
|
|
16
|
+
connect(storedWalletType).catch((error) => {
|
|
17
|
+
console.error('Failed to reconnect wallet:', error);
|
|
18
|
+
disconnect();
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}, []);
|
|
22
|
+
const connect = useCallback(async (walletType) => {
|
|
23
|
+
await walletConnection.connect(walletType);
|
|
24
|
+
setAddress(await walletConnection.getAddress());
|
|
25
|
+
setSigner(walletConnection.signer);
|
|
26
|
+
setNetwork(await walletConnection.getNetwork());
|
|
27
|
+
setProvider(await walletConnection.getProvider());
|
|
28
|
+
setIsConnected(true);
|
|
29
|
+
localStorage.setItem('walletType', walletType);
|
|
30
|
+
if (walletConnection.signer instanceof UnisatSigner) {
|
|
31
|
+
walletConnection.signer.unisat.on('disconnect', () => {
|
|
32
|
+
disconnect();
|
|
33
|
+
});
|
|
34
|
+
walletConnection.signer.unisat.on('accountsChanged', async () => {
|
|
35
|
+
setAddress(await walletConnection.getAddress());
|
|
36
|
+
});
|
|
37
|
+
walletConnection.signer.unisat.on('chainChanged', async () => {
|
|
38
|
+
setNetwork(await walletConnection.getNetwork());
|
|
39
|
+
setProvider(await walletConnection.getProvider());
|
|
40
|
+
});
|
|
41
|
+
walletConnection.signer.unisat.on('networkChanged', async () => {
|
|
42
|
+
setNetwork(await walletConnection.getNetwork());
|
|
43
|
+
setProvider(await walletConnection.getProvider());
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}, [walletConnection]);
|
|
47
|
+
const disconnect = useCallback(() => {
|
|
48
|
+
walletConnection.disconnect();
|
|
49
|
+
setAddress(null);
|
|
50
|
+
setSigner(null);
|
|
51
|
+
setNetwork(null);
|
|
52
|
+
setProvider(null);
|
|
53
|
+
setIsConnected(false);
|
|
54
|
+
localStorage.removeItem('walletType');
|
|
55
|
+
}, [walletConnection]);
|
|
56
|
+
const value = {
|
|
57
|
+
connect,
|
|
58
|
+
disconnect,
|
|
59
|
+
address,
|
|
60
|
+
signer,
|
|
61
|
+
network,
|
|
62
|
+
provider,
|
|
63
|
+
isConnected,
|
|
64
|
+
};
|
|
65
|
+
return _jsx(WalletContext.Provider, { value: value, children: children });
|
|
66
|
+
};
|
|
67
|
+
export const useWallet = () => {
|
|
68
|
+
const context = useContext(WalletContext);
|
|
69
|
+
if (!context) {
|
|
70
|
+
throw new Error('useWallet must be used within a WalletProvider');
|
|
71
|
+
}
|
|
72
|
+
return context;
|
|
73
|
+
};
|
package/build/index.d.ts
ADDED
package/build/index.js
ADDED
package/cjs/package.json
ADDED
package/eslint.config.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import eslint from '@eslint/js';
|
|
4
|
+
import tseslint from 'typescript-eslint';
|
|
5
|
+
|
|
6
|
+
export default tseslint.config(
|
|
7
|
+
eslint.configs.recommended,
|
|
8
|
+
...tseslint.configs.strictTypeChecked,
|
|
9
|
+
{
|
|
10
|
+
languageOptions: {
|
|
11
|
+
parserOptions: {
|
|
12
|
+
projectService: true,
|
|
13
|
+
tsconfigDirName: import.meta.dirname,
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
rules: {
|
|
17
|
+
'no-undef': 'off',
|
|
18
|
+
'@typescript-eslint/no-unused-vars': 'off',
|
|
19
|
+
'no-empty': 'off',
|
|
20
|
+
'@typescript-eslint/restrict-template-expressions': 'off',
|
|
21
|
+
'@typescript-eslint/only-throw-error': 'off',
|
|
22
|
+
'@typescript-eslint/no-unnecessary-condition': 'off',
|
|
23
|
+
'@typescript-eslint/unbound-method': 'warn',
|
|
24
|
+
'@typescript-eslint/no-confusing-void-expression': 'off',
|
|
25
|
+
'@typescript-eslint/no-extraneous-class': 'off',
|
|
26
|
+
'no-async-promise-executor': 'off',
|
|
27
|
+
'@typescript-eslint/no-misused-promises': 'off',
|
|
28
|
+
'@typescript-eslint/no-unnecessary-type-parameters': 'off',
|
|
29
|
+
'@typescript-eslint/no-duplicate-enum-values': 'off',
|
|
30
|
+
'prefer-spread': 'off',
|
|
31
|
+
'@typescript-eslint/no-empty-object-type': 'off',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
files: ['**/*.js'],
|
|
36
|
+
...tseslint.configs.disableTypeChecked,
|
|
37
|
+
},
|
|
38
|
+
);
|
package/gulpfile.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import gulp from 'gulp';
|
|
2
|
+
import gulpcache from 'gulp-cached';
|
|
3
|
+
import gulpESLintNew from 'gulp-eslint-new';
|
|
4
|
+
|
|
5
|
+
import gulpClean from 'gulp-clean';
|
|
6
|
+
import logger from 'gulp-logger-new';
|
|
7
|
+
import ts from 'gulp-typescript';
|
|
8
|
+
|
|
9
|
+
process.on('uncaughtException', function (err) {
|
|
10
|
+
console.log('Caught exception: ', err);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const tsProject = ts.createProject('tsconfig.json', {
|
|
14
|
+
jsx: 'react-jsx',
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
function buildESM() {
|
|
18
|
+
return tsProject
|
|
19
|
+
.src()
|
|
20
|
+
.pipe(gulpcache('ts-esm'))
|
|
21
|
+
.pipe(
|
|
22
|
+
logger({
|
|
23
|
+
before: 'Starting...',
|
|
24
|
+
after: 'Project compiled!',
|
|
25
|
+
extname: '.js',
|
|
26
|
+
showChange: true,
|
|
27
|
+
}),
|
|
28
|
+
)
|
|
29
|
+
.pipe(gulpESLintNew())
|
|
30
|
+
.pipe(gulpESLintNew.format())
|
|
31
|
+
.pipe(tsProject())
|
|
32
|
+
.pipe(gulp.dest('build'));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function clean() {
|
|
36
|
+
return gulp.src('./build/src', { read: false }).pipe(gulpClean());
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const build = buildESM;
|
|
40
|
+
export default build;
|
|
41
|
+
|
|
42
|
+
export function watch() {
|
|
43
|
+
gulp.watch(
|
|
44
|
+
['src/**/*.ts', 'src/**/*.tsx', 'src/**/*.js', 'src/**/*.jsx'],
|
|
45
|
+
gulp.series(buildESM),
|
|
46
|
+
);
|
|
47
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@btc-vision/walletconnect",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"author": "impredmet",
|
|
6
|
+
"description": "OPNet Wallet Connect library allows you to connect to any WalletConnect compatible wallet.",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=20.0.0"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"browser": "./browser/index.js",
|
|
13
|
+
"import": "./build/index.js",
|
|
14
|
+
"require": "./build/index.js",
|
|
15
|
+
"types": "./build/index.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"./browser": {
|
|
18
|
+
"import": "./browser/index.js",
|
|
19
|
+
"require": "./browser/index.js",
|
|
20
|
+
"types": "./browser/index.d.ts"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"browser": {
|
|
24
|
+
"./build/index.d.ts": "./browser/index.d.ts",
|
|
25
|
+
"./build/index.js": "./browser/index.js",
|
|
26
|
+
"Buffer": "buffer",
|
|
27
|
+
"crypto": "./src/crypto/crypto-browser.js",
|
|
28
|
+
"stream": "stream-browserify",
|
|
29
|
+
"zlib": "browserify-zlib"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://opnet.org",
|
|
32
|
+
"keywords": [
|
|
33
|
+
"opnet",
|
|
34
|
+
"bsi",
|
|
35
|
+
"bsi-binary",
|
|
36
|
+
"bsi-bitcoin-rpc",
|
|
37
|
+
"walletconnect",
|
|
38
|
+
"wallet",
|
|
39
|
+
"connect",
|
|
40
|
+
"bitcoin",
|
|
41
|
+
"btc",
|
|
42
|
+
"bitcoin smart contracts",
|
|
43
|
+
"smart inscriptions",
|
|
44
|
+
"ordinals"
|
|
45
|
+
],
|
|
46
|
+
"license": "MIT",
|
|
47
|
+
"main": "build/index.js",
|
|
48
|
+
"types": "build/index.d.ts",
|
|
49
|
+
"typings": "build/index.d.ts",
|
|
50
|
+
"module": "build/index.js",
|
|
51
|
+
"publishConfig": {
|
|
52
|
+
"access": "public",
|
|
53
|
+
"tag": "latest"
|
|
54
|
+
},
|
|
55
|
+
"repository": {
|
|
56
|
+
"type": "git",
|
|
57
|
+
"url": "git://github.com/btc-vision/walletconnect.git"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"watch": "gulp watch",
|
|
61
|
+
"build": "gulp build",
|
|
62
|
+
"setup": "npm i && npm run build",
|
|
63
|
+
"browserBuild": "webpack --mode production"
|
|
64
|
+
},
|
|
65
|
+
"peerDependencies": {
|
|
66
|
+
"react": "^18",
|
|
67
|
+
"react-dom": "^18"
|
|
68
|
+
},
|
|
69
|
+
"devDependencies": {
|
|
70
|
+
"@babel/core": "^7.26.0",
|
|
71
|
+
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
|
72
|
+
"@babel/plugin-transform-runtime": "^7.25.9",
|
|
73
|
+
"@babel/preset-env": "^7.26.0",
|
|
74
|
+
"@babel/preset-flow": "^7.25.9",
|
|
75
|
+
"@babel/preset-react": "^7.25.9",
|
|
76
|
+
"@babel/preset-typescript": "^7.26.0",
|
|
77
|
+
"@types/node": "^22.10.2",
|
|
78
|
+
"@types/react": "^18",
|
|
79
|
+
"@types/sha.js": "^2.4.4",
|
|
80
|
+
"eslint": "^9.14.0",
|
|
81
|
+
"gulp": "^5.0.0",
|
|
82
|
+
"gulp-cached": "^1.1.1",
|
|
83
|
+
"gulp-typescript": "^6.0.0-alpha.1",
|
|
84
|
+
"https-browserify": "^1.0.0",
|
|
85
|
+
"os-browserify": "^0.3.0",
|
|
86
|
+
"prettier": "^3.3.3",
|
|
87
|
+
"react": "^18",
|
|
88
|
+
"react-dom": "^18.0.0",
|
|
89
|
+
"stream-browserify": "^3.0.0",
|
|
90
|
+
"stream-http": "^3.2.0",
|
|
91
|
+
"typedoc": "^0.27.6",
|
|
92
|
+
"typescript-eslint": "^8.19.0",
|
|
93
|
+
"webpack-cli": "^6.0.1"
|
|
94
|
+
},
|
|
95
|
+
"dependencies": {
|
|
96
|
+
"@babel/plugin-proposal-object-rest-spread": "^7.20.7",
|
|
97
|
+
"@bitcoinerlab/secp256k1": "^1.1.1",
|
|
98
|
+
"@btc-vision/bitcoin": "^6.3.6",
|
|
99
|
+
"@btc-vision/bitcoin-rpc": "^1.0.0",
|
|
100
|
+
"@btc-vision/logger": "^1.0.6",
|
|
101
|
+
"@btc-vision/transaction": "^1.2.10",
|
|
102
|
+
"@eslint/js": "^9.14.0",
|
|
103
|
+
"@noble/secp256k1": "^2.1.0",
|
|
104
|
+
"assert": "^2.1.0",
|
|
105
|
+
"babel-loader": "^9.2.1",
|
|
106
|
+
"babel-plugin-transform-import-meta": "^2.2.1",
|
|
107
|
+
"babel-preset-react": "^6.24.1",
|
|
108
|
+
"babelify": "^10.0.0",
|
|
109
|
+
"bech32": "^2.0.0",
|
|
110
|
+
"bip174": "^2.1.1",
|
|
111
|
+
"bip32": "^5.0.0-rc.0",
|
|
112
|
+
"browserify-zlib": "^0.2.0",
|
|
113
|
+
"buffer": "^6.0.3",
|
|
114
|
+
"ecpair": "^2.1.0",
|
|
115
|
+
"gulp-clean": "^0.4.0",
|
|
116
|
+
"gulp-eslint-new": "^2.4.0",
|
|
117
|
+
"gulp-logger-new": "^1.0.1",
|
|
118
|
+
"opnet": "^1.2.23",
|
|
119
|
+
"process": "^0.11.10",
|
|
120
|
+
"sha.js": "^2.4.11",
|
|
121
|
+
"ts-loader": "^9.5.1",
|
|
122
|
+
"ts-node": "^10.9.2",
|
|
123
|
+
"typescript": "^5.7.2",
|
|
124
|
+
"webpack": "^5.97.1"
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { Network, networks } from '@btc-vision/bitcoin';
|
|
2
|
+
import { Address, Unisat, UnisatChainType, UnisatSigner } from '@btc-vision/transaction';
|
|
3
|
+
import { JSONRpcProvider } from 'opnet';
|
|
4
|
+
|
|
5
|
+
export enum SupportedWallets {
|
|
6
|
+
OP_WALLET = 'op_wallet',
|
|
7
|
+
}
|
|
8
|
+
export type Signers = UnisatSigner;
|
|
9
|
+
export type Wallets = Unisat;
|
|
10
|
+
|
|
11
|
+
export class WalletConnection {
|
|
12
|
+
public signer: Signers | null = null;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @description Connect to the wallet
|
|
16
|
+
* @param {SupportedWallets} walletType
|
|
17
|
+
* @returns {Promise<void>}
|
|
18
|
+
*/
|
|
19
|
+
public async connect(walletType: SupportedWallets): Promise<void> {
|
|
20
|
+
// TODO: When more wallets are supported, make them disconnect before connecting to the new one
|
|
21
|
+
switch (walletType) {
|
|
22
|
+
case SupportedWallets.OP_WALLET:
|
|
23
|
+
if (this.signer instanceof UnisatSigner) return;
|
|
24
|
+
|
|
25
|
+
if (window.opnet || window.unisat) {
|
|
26
|
+
try {
|
|
27
|
+
const signer = new UnisatSigner();
|
|
28
|
+
await signer.init();
|
|
29
|
+
|
|
30
|
+
this.signer = signer;
|
|
31
|
+
return;
|
|
32
|
+
} catch (error: unknown) {
|
|
33
|
+
if (error instanceof Error) throw new Error(error.message);
|
|
34
|
+
|
|
35
|
+
throw new Error(`Unknown error: ${error}`);
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
throw new Error('OP Wallet not found');
|
|
39
|
+
}
|
|
40
|
+
default:
|
|
41
|
+
throw new Error('Unsupported wallet');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @description Disconnect from the wallet
|
|
47
|
+
* @returns {void}
|
|
48
|
+
*/
|
|
49
|
+
public disconnect(): void {
|
|
50
|
+
if (!this.signer) throw new Error('Wallet not connected');
|
|
51
|
+
|
|
52
|
+
if (this.signer instanceof UnisatSigner) this.signer.unisat.disconnect();
|
|
53
|
+
|
|
54
|
+
this.signer = null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @description Get the address of the connected wallet
|
|
59
|
+
* @returns {Promise<Address>}
|
|
60
|
+
*/
|
|
61
|
+
public async getAddress(): Promise<Address> {
|
|
62
|
+
if (!this.signer) throw new Error('Wallet not connected');
|
|
63
|
+
|
|
64
|
+
if (this.signer instanceof UnisatSigner) {
|
|
65
|
+
const publicKey = await this.signer.unisat.getPublicKey();
|
|
66
|
+
|
|
67
|
+
return Address.fromString(publicKey);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
throw new Error('Unsupported wallet');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @description Get the network of the connected wallet
|
|
75
|
+
* @returns {Promise<Network>}
|
|
76
|
+
*/
|
|
77
|
+
public async getNetwork(): Promise<Network> {
|
|
78
|
+
if (!this.signer) throw new Error('Wallet not connected');
|
|
79
|
+
|
|
80
|
+
if (this.signer instanceof UnisatSigner) {
|
|
81
|
+
const chain = await this.signer.unisat.getChain();
|
|
82
|
+
|
|
83
|
+
// TODO: Add Fractal network
|
|
84
|
+
switch (chain.enum) {
|
|
85
|
+
case UnisatChainType.BITCOIN_MAINNET:
|
|
86
|
+
return networks.bitcoin;
|
|
87
|
+
case UnisatChainType.BITCOIN_TESTNET:
|
|
88
|
+
return networks.testnet;
|
|
89
|
+
case UnisatChainType.BITCOIN_REGTEST:
|
|
90
|
+
return networks.regtest;
|
|
91
|
+
default:
|
|
92
|
+
throw new Error('Unsupported network');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
throw new Error('Unsupported wallet');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @description Get the provider of the connected wallet
|
|
101
|
+
* @returns {Promise<JSONRpcProvider>}
|
|
102
|
+
*/
|
|
103
|
+
public async getProvider(): Promise<JSONRpcProvider> {
|
|
104
|
+
if (!this.signer) throw new Error('Wallet not connected');
|
|
105
|
+
|
|
106
|
+
if (this.signer instanceof UnisatSigner) {
|
|
107
|
+
const network = await this.getNetwork();
|
|
108
|
+
|
|
109
|
+
// TODO: Add Fractal network
|
|
110
|
+
switch (network.bech32) {
|
|
111
|
+
case networks.bitcoin.bech32:
|
|
112
|
+
return new JSONRpcProvider('https://api.opnet.org', networks.bitcoin);
|
|
113
|
+
case networks.testnet.bech32:
|
|
114
|
+
return new JSONRpcProvider('https://testnet.opnet.org', networks.testnet);
|
|
115
|
+
case networks.regtest.bech32:
|
|
116
|
+
return new JSONRpcProvider('https://regtest.opnet.org', networks.regtest);
|
|
117
|
+
default:
|
|
118
|
+
throw new Error('Unsupported network');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
throw new Error('Unsupported wallet');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export default WalletConnection;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Network } from '@btc-vision/bitcoin';
|
|
2
|
+
import { Address, UnisatSigner } from '@btc-vision/transaction';
|
|
3
|
+
import { JSONRpcProvider } from 'opnet';
|
|
4
|
+
import React, { createContext, useCallback, useContext, useEffect, useState } from 'react';
|
|
5
|
+
import WalletConnection, { Signers, SupportedWallets } from './WalletConnection';
|
|
6
|
+
|
|
7
|
+
interface WalletContextType {
|
|
8
|
+
connect: (walletType: SupportedWallets) => Promise<void>;
|
|
9
|
+
disconnect: () => void;
|
|
10
|
+
address: Address | null;
|
|
11
|
+
signer: Signers | null;
|
|
12
|
+
network: Network | null;
|
|
13
|
+
provider: JSONRpcProvider | null;
|
|
14
|
+
isConnected: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const WalletContext = createContext<WalletContextType | undefined>(undefined);
|
|
18
|
+
|
|
19
|
+
export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
20
|
+
const [walletConnection] = useState(new WalletConnection());
|
|
21
|
+
const [address, setAddress] = useState<Address | null>(null);
|
|
22
|
+
const [signer, setSigner] = useState<Signers | null>(null);
|
|
23
|
+
const [network, setNetwork] = useState<Network | null>(null);
|
|
24
|
+
const [provider, setProvider] = useState<JSONRpcProvider | null>(null);
|
|
25
|
+
const [isConnected, setIsConnected] = useState(false);
|
|
26
|
+
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
const storedWalletType = localStorage.getItem('walletType') as SupportedWallets | null;
|
|
29
|
+
|
|
30
|
+
if (storedWalletType) {
|
|
31
|
+
connect(storedWalletType).catch((error: unknown) => {
|
|
32
|
+
console.error('Failed to reconnect wallet:', error);
|
|
33
|
+
disconnect();
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}, []);
|
|
37
|
+
|
|
38
|
+
const connect = useCallback(
|
|
39
|
+
async (walletType: SupportedWallets) => {
|
|
40
|
+
await walletConnection.connect(walletType);
|
|
41
|
+
|
|
42
|
+
setAddress(await walletConnection.getAddress());
|
|
43
|
+
setSigner(walletConnection.signer);
|
|
44
|
+
setNetwork(await walletConnection.getNetwork());
|
|
45
|
+
setProvider(await walletConnection.getProvider());
|
|
46
|
+
setIsConnected(true);
|
|
47
|
+
localStorage.setItem('walletType', walletType);
|
|
48
|
+
|
|
49
|
+
if (walletConnection.signer instanceof UnisatSigner) {
|
|
50
|
+
walletConnection.signer.unisat.on('disconnect', () => {
|
|
51
|
+
disconnect();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
walletConnection.signer.unisat.on('accountsChanged', async () => {
|
|
55
|
+
setAddress(await walletConnection.getAddress());
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
walletConnection.signer.unisat.on('chainChanged', async () => {
|
|
59
|
+
setNetwork(await walletConnection.getNetwork());
|
|
60
|
+
setProvider(await walletConnection.getProvider());
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
walletConnection.signer.unisat.on('networkChanged', async () => {
|
|
64
|
+
setNetwork(await walletConnection.getNetwork());
|
|
65
|
+
setProvider(await walletConnection.getProvider());
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
[walletConnection],
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const disconnect = useCallback(() => {
|
|
73
|
+
walletConnection.disconnect();
|
|
74
|
+
setAddress(null);
|
|
75
|
+
setSigner(null);
|
|
76
|
+
setNetwork(null);
|
|
77
|
+
setProvider(null);
|
|
78
|
+
setIsConnected(false);
|
|
79
|
+
localStorage.removeItem('walletType');
|
|
80
|
+
}, [walletConnection]);
|
|
81
|
+
|
|
82
|
+
const value = {
|
|
83
|
+
connect,
|
|
84
|
+
disconnect,
|
|
85
|
+
address,
|
|
86
|
+
signer,
|
|
87
|
+
network,
|
|
88
|
+
provider,
|
|
89
|
+
isConnected,
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
return <WalletContext.Provider value={value}>{children}</WalletContext.Provider>;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export const useWallet = (): WalletContextType => {
|
|
96
|
+
const context = useContext(WalletContext);
|
|
97
|
+
if (!context) {
|
|
98
|
+
throw new Error('useWallet must be used within a WalletProvider');
|
|
99
|
+
}
|
|
100
|
+
return context;
|
|
101
|
+
};
|
package/src/index.ts
ADDED