diff --git a/advanced/dapps/react-dapp-v2/package.json b/advanced/dapps/react-dapp-v2/package.json
index dda7e9c79..a4ef588ed 100644
--- a/advanced/dapps/react-dapp-v2/package.json
+++ b/advanced/dapps/react-dapp-v2/package.json
@@ -18,6 +18,7 @@
"@kadena/types": "^0.6.0",
"@multiversx/sdk-core": "12.18.0",
"@multiversx/sdk-wallet": "4.2.0",
+ "@noble/curves": "^1.6.0",
"@polkadot/util-crypto": "^10.1.2",
"@solana/web3.js": "^1.36.0",
"@walletconnect/encoding": "^1.0.1",
@@ -26,6 +27,8 @@
"@walletconnect/utils": "2.16.1",
"@web3modal/standalone": "2.4.3",
"axios": "^1.0.0",
+ "bitcoinjs-lib": "^6.1.5",
+ "bitcoinjs-message": "^2.2.0",
"blockies-ts": "^1.0.0",
"bs58": "^5.0.0",
"cosmos-wallet": "^1.2.0",
diff --git a/advanced/dapps/react-dapp-v2/public/assets/btc-testnet.png b/advanced/dapps/react-dapp-v2/public/assets/btc-testnet.png
new file mode 100644
index 000000000..b991e4b73
Binary files /dev/null and b/advanced/dapps/react-dapp-v2/public/assets/btc-testnet.png differ
diff --git a/advanced/dapps/react-dapp-v2/src/chains/bip122.ts b/advanced/dapps/react-dapp-v2/src/chains/bip122.ts
new file mode 100644
index 000000000..88077f660
--- /dev/null
+++ b/advanced/dapps/react-dapp-v2/src/chains/bip122.ts
@@ -0,0 +1,41 @@
+import { NamespaceMetadata, ChainMetadata, ChainsMap } from "../helpers";
+
+export const BIP122_MAINNET = "000000000019d6689c085ae165831e93";
+export const BIP122_TESTNET = "000000000933ea01ad0ee984209779ba";
+
+export const BtcChainData: ChainsMap = {
+ [BIP122_MAINNET]: {
+ id: `bip122:${BIP122_MAINNET}`,
+ name: "BTC Mainnet",
+ rpc: [],
+ slip44: 0,
+ testnet: false,
+ },
+ [BIP122_TESTNET]: {
+ id: `bip122:${BIP122_TESTNET}`,
+ name: "BTC Testnet",
+ rpc: [],
+ slip44: 501,
+ testnet: true,
+ },
+};
+
+export const BtcMetadata: NamespaceMetadata = {
+ [BIP122_MAINNET]: {
+ logo: "/assets/btc-testnet.png",
+ rgb: "247, 147, 25",
+ },
+ [BIP122_TESTNET]: {
+ logo: "/assets/btc-testnet.png",
+ rgb: "247, 147, 25",
+ },
+};
+
+export function getChainMetadata(chainId: string): ChainMetadata {
+ const reference = chainId.split(":")[1];
+ const metadata = BtcMetadata[reference];
+ if (typeof metadata === "undefined") {
+ throw new Error(`No chain metadata found for chainId: ${chainId}`);
+ }
+ return metadata;
+}
diff --git a/advanced/dapps/react-dapp-v2/src/chains/index.ts b/advanced/dapps/react-dapp-v2/src/chains/index.ts
index 47878f76d..ce02b603e 100644
--- a/advanced/dapps/react-dapp-v2/src/chains/index.ts
+++ b/advanced/dapps/react-dapp-v2/src/chains/index.ts
@@ -9,6 +9,7 @@ import * as multiversx from "./multiversx";
import * as tron from "./tron";
import * as tezos from "./tezos";
import * as kadena from "./kadena";
+import * as bip122 from "./bip122";
import { ChainMetadata, ChainRequestRender } from "../helpers";
@@ -33,6 +34,8 @@ export function getChainMetadata(chainId: string): ChainMetadata {
return tron.getChainMetadata(chainId);
case "tezos":
return tezos.getChainMetadata(chainId);
+ case "bip122":
+ return bip122.getChainMetadata(chainId);
default:
throw new Error(`No metadata handler for namespace ${namespace}`);
}
diff --git a/advanced/dapps/react-dapp-v2/src/components/Asset.tsx b/advanced/dapps/react-dapp-v2/src/components/Asset.tsx
index 9e726b408..c74990211 100644
--- a/advanced/dapps/react-dapp-v2/src/components/Asset.tsx
+++ b/advanced/dapps/react-dapp-v2/src/components/Asset.tsx
@@ -10,6 +10,9 @@ import { getChainMetadata } from "../chains";
const xdaiLogo = getChainMetadata("eip155:100").logo;
const maticLogo = getChainMetadata("eip155:137").logo;
const kadenaLogo = getChainMetadata("kadena:testnet04").logo;
+const btcLogo = getChainMetadata(
+ "bip122:000000000933ea01ad0ee984209779ba"
+).logo;
const SAsset = styled.div`
width: 100%;
@@ -48,6 +51,8 @@ function getAssetIcon(asset: AssetData): JSX.Element {
return ;
case "kda":
return ;
+ case "btc":
+ return ;
default:
return ;
}
diff --git a/advanced/dapps/react-dapp-v2/src/constants/default.ts b/advanced/dapps/react-dapp-v2/src/constants/default.ts
index 50fa43af4..91139a41b 100644
--- a/advanced/dapps/react-dapp-v2/src/constants/default.ts
+++ b/advanced/dapps/react-dapp-v2/src/constants/default.ts
@@ -19,6 +19,7 @@ export const DEFAULT_MAIN_CHAINS = [
"tron:0x2b6653dc",
"tezos:mainnet",
"kadena:mainnet01",
+ "bip122:000000000019d6689c085ae165831e93",
];
export const DEFAULT_TEST_CHAINS = [
@@ -38,6 +39,7 @@ export const DEFAULT_TEST_CHAINS = [
"tron:0xcd8690dc",
"tezos:testnet",
"kadena:testnet04",
+ "bip122:000000000933ea01ad0ee984209779ba",
];
export const DEFAULT_CHAINS = [...DEFAULT_MAIN_CHAINS, ...DEFAULT_TEST_CHAINS];
@@ -272,6 +274,18 @@ export enum DEFAULT_KADENA_METHODS {
}
export enum DEFAULT_KADENA_EVENTS {}
+/**
+ * BITCOIN
+ */
+export enum DEFAULT_BIP122_METHODS {
+ BIP122_SEND_TRANSACTION = "sendTransfer",
+ BIP122_GET_ACCOUNT_ADDRESSES = "getAccountAddresses",
+ BIP122_SIGN_MESSAGE = "signMessage",
+ BIP122_SIGN_PSBT = "signPsbt",
+}
+export enum DEFAULT_BIP122_EVENTS {
+ BIP122_ADDRESS_CHANGED = "bip122_addressesChanged",
+}
export const REGIONALIZED_RELAYER_ENDPOINTS: RelayerType[] = [
{
diff --git a/advanced/dapps/react-dapp-v2/src/contexts/ChainDataContext.tsx b/advanced/dapps/react-dapp-v2/src/contexts/ChainDataContext.tsx
index 8b86d9471..4c138451a 100644
--- a/advanced/dapps/react-dapp-v2/src/contexts/ChainDataContext.tsx
+++ b/advanced/dapps/react-dapp-v2/src/contexts/ChainDataContext.tsx
@@ -16,6 +16,7 @@ import { CosmosChainData } from "../chains/cosmos";
import { EIP155ChainData } from "../chains/eip155";
import { TezosChainData } from "../chains/tezos";
import { KadenaChainData } from "../chains/kadena";
+import { BtcChainData } from "../chains/bip122";
/**
* Types
@@ -73,6 +74,9 @@ export function ChainDataContextProvider({
case "kadena":
chains = KadenaChainData;
break;
+ case "bip122":
+ chains = BtcChainData;
+ break;
default:
console.error("Unknown chain namespace: ", namespace);
}
diff --git a/advanced/dapps/react-dapp-v2/src/contexts/ClientContext.tsx b/advanced/dapps/react-dapp-v2/src/contexts/ClientContext.tsx
index 0ca8990d1..28f1b2872 100644
--- a/advanced/dapps/react-dapp-v2/src/contexts/ClientContext.tsx
+++ b/advanced/dapps/react-dapp-v2/src/contexts/ClientContext.tsx
@@ -49,6 +49,7 @@ interface IContext {
setChains: any;
setRelayerRegion: any;
origin: string;
+ setAccounts: any;
}
/**
@@ -63,6 +64,16 @@ const web3Modal = new Web3Modal({
projectId: DEFAULT_PROJECT_ID,
themeMode: "light",
walletConnectVersion: 2,
+ mobileWallets: [
+ {
+ id: "bifrost",
+ name: "Bifrost Wallet",
+ links: {
+ native: "bifrostwallet://",
+ universal: "https://bifrostwallet.com",
+ },
+ },
+ ],
});
/**
@@ -106,7 +117,6 @@ export function ClientContextProvider({
const [namespace, reference, address] = account.split(":");
const chainId = `${namespace}:${reference}`;
const assets = await apiGetAccountBalance(address, chainId);
-
return { account, assets: [assets] };
})
);
@@ -123,6 +133,11 @@ export function ClientContextProvider({
}
};
+ useMemo(() => {
+ if (!accounts.length) return;
+ getAccountBalances(accounts);
+ }, [accounts]);
+
const onSessionConnected = useCallback(
async (_session: SessionTypes.Struct) => {
const allNamespaceAccounts = Object.values(_session.namespaces)
@@ -147,26 +162,17 @@ export function ClientContextProvider({
}
console.log("connect, pairing topic is:", pairing?.topic);
try {
- const requiredNamespaces = getRequiredNamespaces(chains);
- console.log(
- "requiredNamespaces config for connect:",
- requiredNamespaces
- );
- const optionalNamespaces = getOptionalNamespaces(chains);
- console.log(
- "optionalNamespaces config for connect:",
- optionalNamespaces
- );
+ const namespacesToRequest = getRequiredNamespaces(chains);
const { uri, approval } = await client.connect({
pairingTopic: pairing?.topic,
- requiredNamespaces,
- optionalNamespaces,
+ requiredNamespaces: {},
+ optionalNamespaces: namespacesToRequest,
});
// Open QRCode modal if a URI was returned (i.e. we're not connecting an existing pairing).
if (uri) {
// Create a flat array of all requested chains across namespaces.
- const standaloneChains = Object.values(requiredNamespaces)
+ const standaloneChains = Object.values(namespacesToRequest)
.map((namespace) => namespace.chains)
.flat() as string[];
@@ -375,6 +381,7 @@ export function ClientContextProvider({
setChains,
setRelayerRegion,
origin,
+ setAccounts,
}),
[
pairings,
@@ -392,6 +399,7 @@ export function ClientContextProvider({
setChains,
setRelayerRegion,
origin,
+ setAccounts,
]
);
diff --git a/advanced/dapps/react-dapp-v2/src/contexts/JsonRpcContext.tsx b/advanced/dapps/react-dapp-v2/src/contexts/JsonRpcContext.tsx
index fdec84c1a..eb8d3631f 100644
--- a/advanced/dapps/react-dapp-v2/src/contexts/JsonRpcContext.tsx
+++ b/advanced/dapps/react-dapp-v2/src/contexts/JsonRpcContext.tsx
@@ -3,6 +3,8 @@ import { createContext, ReactNode, useContext, useState } from "react";
import * as encoding from "@walletconnect/encoding";
import { Transaction as EthTransaction } from "@ethereumjs/tx";
import { recoverTransaction } from "@celo/wallet-base";
+import * as bitcoin from "bitcoinjs-lib";
+
import {
formatDirectSignDoc,
stringifySignDocValues,
@@ -28,6 +30,7 @@ import {
} from "@kadena/client";
import { PactNumber } from "@kadena/pactjs";
import {
+ IUTXO,
KadenaAccount,
eip712,
formatTestBatchCall,
@@ -54,6 +57,7 @@ import {
SendCallsParams,
GetCapabilitiesResult,
GetCallsResult,
+ DEFAULT_BIP122_METHODS,
DEFAULT_EIP7715_METHODS,
WalletGrantPermissionsParameters,
WalletGrantPermissionsReturnType,
@@ -69,8 +73,15 @@ import {
SignableMessage,
} from "@multiversx/sdk-core";
import { UserVerifier } from "@multiversx/sdk-wallet/out/userVerifier";
-import { SignClient } from "@walletconnect/sign-client/dist/types/client";
import { parseEther } from "ethers/lib/utils";
+import {
+ apiGetAddressUtxos,
+ calculateChange,
+ getAvailableBalanceFromUtxos,
+ isOrdinalAddress,
+ isValidBip122Signature,
+} from "../helpers/bip122";
+import { getAddressFromAccount } from "@walletconnect/utils";
/**
* Types
@@ -137,6 +148,12 @@ interface IContext {
testSign: TRpcRequestCallback;
testQuicksign: TRpcRequestCallback;
};
+ bip122Rpc: {
+ testGetAccountAddresses: TRpcRequestCallback;
+ testSignMessage: TRpcRequestCallback;
+ testSendTransaction: TRpcRequestCallback;
+ testSignPsbt: TRpcRequestCallback;
+ };
rpcResult?: IFormattedRpcResponse | null;
isRpcRequestPending: boolean;
isTestnet: boolean;
@@ -164,7 +181,7 @@ export function JsonRpcContextProvider({
null
);
- const { client, session, accounts, balances, solanaPublicKeys } =
+ const { client, session, accounts, balances, solanaPublicKeys, setAccounts } =
useWalletConnectClient();
const { chainData } = useChainData();
@@ -872,7 +889,7 @@ export function JsonRpcContextProvider({
})),
transaction: transaction
.serialize({ verifySignatures: false })
- .toString('base64'),
+ .toString("base64"),
},
},
});
@@ -1640,6 +1657,231 @@ export function JsonRpcContextProvider({
),
};
+ const bip122Rpc = {
+ testSignMessage: _createJsonRpcRequestHandler(
+ async (
+ chainId: string,
+ address: string
+ ): Promise => {
+ console.log("testSignMessage", chainId, address);
+ const method = DEFAULT_BIP122_METHODS.BIP122_SIGN_MESSAGE;
+ const message = "This is a message to be signed for BIP122";
+ const shouldAddAddress = address !== getAddressFromAccount(accounts[0]);
+ const result = await client!.request<{
+ signature: string;
+ address: string;
+ }>({
+ topic: session!.topic,
+ chainId: chainId,
+ request: {
+ method,
+ params: {
+ message,
+ account: getAddressFromAccount(accounts[0]),
+ address: shouldAddAddress ? address : undefined,
+ },
+ },
+ });
+
+ return {
+ method,
+ address: address,
+ valid: await isValidBip122Signature(
+ address,
+ result.signature,
+ message
+ ),
+ result: result.signature,
+ };
+ }
+ ),
+ testSendTransaction: _createJsonRpcRequestHandler(
+ async (
+ chainId: string,
+ address: string
+ ): Promise => {
+ const method = DEFAULT_BIP122_METHODS.BIP122_SEND_TRANSACTION;
+
+ const utxos = await apiGetAddressUtxos(address, chainId);
+ console.log("utxos", utxos);
+ const availableBalance = getAvailableBalanceFromUtxos(utxos); // in satoshis
+ console.log("availableBalance", availableBalance);
+ const req = {
+ account: address,
+ recipientAddress: address,
+ amount: "550",
+ };
+ console.log("request", {
+ method,
+ params: req,
+ chainId,
+ });
+
+ const result = await client!.request<{ txid: string }>({
+ topic: session!.topic,
+ chainId: chainId,
+ request: {
+ method,
+ params: req,
+ },
+ });
+ console.log("result", result);
+ return {
+ method,
+ address: address,
+ valid: true,
+ result: result?.txid,
+ };
+ }
+ ),
+ testSignPsbt: _createJsonRpcRequestHandler(
+ async (
+ chainId: string,
+ address: string
+ ): Promise => {
+ const method = DEFAULT_BIP122_METHODS.BIP122_SIGN_PSBT;
+
+ const utxos = (await apiGetAddressUtxos(address, chainId)) as IUTXO[];
+ if (!utxos || utxos.length === 0) {
+ throw new Error("No UTXOs found for address: " + address);
+ }
+
+ const availableBalance = getAvailableBalanceFromUtxos(utxos); // in satoshis
+ const satoshisToTransfer = 550;
+ if (availableBalance < satoshisToTransfer) {
+ throw new Error(
+ "Insufficient balance: " + availableBalance + " satoshis"
+ );
+ }
+ const network = bitcoin.networks.testnet;
+ const psbt = new bitcoin.Psbt({ network });
+
+ const utxosToSpend: any[] = [];
+ let utxosValue = 0;
+ utxos.forEach((utxo) => {
+ utxosValue += utxo.value;
+ utxosToSpend.push(utxo);
+ if (utxosValue >= satoshisToTransfer) {
+ return;
+ }
+ });
+ const signInputs: unknown[] = [];
+
+ utxosToSpend.forEach((utxo, index) => {
+ psbt.addInput({
+ hash: utxo.txid,
+ index: utxo.vout,
+ witnessUtxo: {
+ script: bitcoin.address.toOutputScript(address, network),
+ value: utxo.value,
+ },
+ });
+ signInputs.push({
+ address,
+ index,
+ sighashTypes: [bitcoin.Transaction.SIGHASH_ALL],
+ });
+ });
+
+ const change = calculateChange(utxosToSpend, satoshisToTransfer, 5);
+ if (change > 0) {
+ psbt.addOutput({
+ address: address,
+ value: change,
+ });
+ }
+
+ psbt.addOutput({
+ address: address,
+ value: satoshisToTransfer,
+ });
+
+ const transaction = psbt.toBase64();
+
+ console.log("availableBalance", availableBalance);
+ const req = {
+ account: address,
+ psbt: transaction,
+ signInputs,
+ broadcast: false,
+ };
+ console.log("signPsbt", {
+ method,
+ params: req,
+ chainId,
+ });
+
+ const result = await client!.request<{ psbt: string }>({
+ topic: session!.topic,
+ chainId: chainId,
+ request: {
+ method,
+ params: req,
+ },
+ });
+ console.log("result", result);
+ const reconstructed = bitcoin.Psbt.fromBase64(result.psbt, { network });
+ return {
+ method,
+ address: address,
+ valid: true,
+ result: reconstructed.extractTransaction().toHex(),
+ };
+ }
+ ),
+ testGetAccountAddresses: _createJsonRpcRequestHandler(
+ async (
+ chainId: string,
+ address: string
+ ): Promise => {
+ const method = DEFAULT_BIP122_METHODS.BIP122_GET_ACCOUNT_ADDRESSES;
+ const isOrdinal = isOrdinalAddress(address);
+ const req = {
+ account: address,
+ intentions: isOrdinal ? ["ordinal"] : ["payment"],
+ };
+ const addresses =
+ session?.sessionProperties?.[
+ `bip122_${DEFAULT_BIP122_METHODS.BIP122_GET_ACCOUNT_ADDRESSES}`
+ ];
+ let result;
+ if (addresses) {
+ console.log("cached addresses", addresses);
+ const parsed = JSON.parse(addresses);
+ result = isOrdinal ? parsed.ordinal : parsed.payment;
+ console.log("parsed", result);
+ } else {
+ console.log("request", {
+ method,
+ params: req,
+ chainId,
+ });
+
+ result = await client!.request({
+ topic: session!.topic,
+ chainId: chainId,
+ request: {
+ method,
+ params: req,
+ },
+ });
+
+ console.log("result", result);
+ }
+
+ const accounts = result.map((r: any) => `${chainId}:${r.address}`);
+ setAccounts((prev: string[]) => [...new Set([...prev, ...accounts])]);
+
+ return {
+ method,
+ address: address,
+ valid: true,
+ result: result.map((r: any) => r.address).join(", "),
+ };
+ }
+ ),
+ };
+
return (
{children}
diff --git a/advanced/dapps/react-dapp-v2/src/helpers/api.ts b/advanced/dapps/react-dapp-v2/src/helpers/api.ts
index 59f304cad..ad3b4e6a7 100644
--- a/advanced/dapps/react-dapp-v2/src/helpers/api.ts
+++ b/advanced/dapps/react-dapp-v2/src/helpers/api.ts
@@ -3,6 +3,7 @@ import { apiGetKadenaAccountBalance } from "./kadena";
import { AssetData } from "./types";
import { PactCommand } from "@kadena/client";
+import { apiGetBip122AccountBalance } from "./bip122";
export type RpcProvidersByChainId = Record<
number,
@@ -155,6 +156,10 @@ export async function apiGetAccountBalance(
);
}
+ if (namespace === "bip122") {
+ return apiGetBip122AccountBalance(address, networkId as string);
+ }
+
if (namespace !== "eip155") {
return { balance: "", symbol: "", name: "" };
}
diff --git a/advanced/dapps/react-dapp-v2/src/helpers/bip122.ts b/advanced/dapps/react-dapp-v2/src/helpers/bip122.ts
new file mode 100644
index 000000000..8f178f1be
--- /dev/null
+++ b/advanced/dapps/react-dapp-v2/src/helpers/bip122.ts
@@ -0,0 +1,78 @@
+import { schnorr } from "@noble/secp256k1";
+import * as bitcoin from "bitcoinjs-lib";
+import BitcoinMessage from "bitcoinjs-message";
+import { convertHexToBase64 } from "./utilities";
+import { IUTXO } from "./types";
+import { BIP122_TESTNET } from "../chains/bip122";
+export async function apiGetBip122AccountBalance(
+ address: string,
+ chainId: string
+) {
+ const utxo = await apiGetAddressUtxos(address, chainId);
+ const balanceInSatoshis = getAvailableBalanceFromUtxos(utxo);
+ const balanceInBtc = balanceInSatoshis * 0.00000001;
+ return { balance: balanceInBtc.toString(), symbol: "BTC", name: "BTC" };
+}
+
+export async function apiGetAddressUtxos(address: string, chainId: string) {
+ const isTestnet = chainId.includes(BIP122_TESTNET);
+ return await (
+ await fetch(
+ `https://mempool.space${
+ isTestnet ? "/testnet" : ""
+ }/api/address/${address}/utxo`
+ )
+ ).json();
+}
+
+export function getAvailableBalanceFromUtxos(utxos: IUTXO[]) {
+ if (!utxos || !utxos.length) {
+ return 0;
+ }
+ return utxos.reduce((acc, { value }) => acc + value, 0);
+}
+
+export function calculateChange(
+ utxos: IUTXO[],
+ amount: number,
+ feeRate: number
+): number {
+ const inputSum = utxos.reduce((sum, utxo) => sum + utxo.value, 0); // Sum of all UTXO values
+ const estimatedSize = 10 + 148 * utxos.length + 34 * 2; // Rough estimate of transaction size
+ const fee = estimatedSize * feeRate; // Transaction fee
+ const change = inputSum - amount - fee; // Calculate change
+ return change;
+}
+
+export async function isValidBip122Signature(
+ address: string,
+ signature: string,
+ message: string
+) {
+ // if taproot address
+ if (address.startsWith("bc1p") || address.startsWith("tb1p")) {
+ // Convert the Ordinals address (Taproot) to the internal public key
+ const decoded = bitcoin.address.fromBech32(address);
+ if (decoded.version !== 1 || decoded.data.length !== 32) {
+ throw new Error("Invalid Taproot address");
+ }
+
+ const publicKey = decoded.data; // The 32-byte internal public key (X coordinate of pubkey)
+
+ // Hash the message using SHA256 (standard Bitcoin message hashing)
+ const messageHash = bitcoin.crypto.sha256(Buffer.from(message));
+
+ // Verify the Schnorr signature using tiny-secp256k1
+ return await schnorr.verify(
+ Buffer.from(signature, "hex"),
+ messageHash,
+ publicKey
+ );
+ }
+
+ return BitcoinMessage.verify(message, address, convertHexToBase64(signature));
+}
+
+export function isOrdinalAddress(address: string) {
+ return address.startsWith("tb1p");
+}
diff --git a/advanced/dapps/react-dapp-v2/src/helpers/namespaces.ts b/advanced/dapps/react-dapp-v2/src/helpers/namespaces.ts
index 553f7b53d..f5363c51b 100644
--- a/advanced/dapps/react-dapp-v2/src/helpers/namespaces.ts
+++ b/advanced/dapps/react-dapp-v2/src/helpers/namespaces.ts
@@ -19,6 +19,8 @@ import {
DEFAULT_TEZOS_METHODS,
DEFAULT_TEZOS_EVENTS,
DEFAULT_OPTIONAL_METHODS,
+ DEFAULT_BIP122_METHODS,
+ DEFAULT_BIP122_EVENTS,
} from "../constants";
export const getNamespacesFromChains = (chains: string[]) => {
@@ -53,6 +55,8 @@ export const getSupportedRequiredMethodsByNamespace = (namespace: string) => {
return Object.values(DEFAULT_TEZOS_METHODS);
case "kadena":
return Object.values(DEFAULT_KADENA_METHODS);
+ case "bip122":
+ return Object.values(DEFAULT_BIP122_METHODS);
default:
throw new Error(
`No default required methods for namespace: ${namespace}`
@@ -72,6 +76,7 @@ export const getSupportedOptionalMethodsByNamespace = (namespace: string) => {
case "tron":
case "tezos":
case "kadena":
+ case "bip122":
return [];
default:
throw new Error(
@@ -100,6 +105,8 @@ export const getSupportedEventsByNamespace = (namespace: string) => {
return Object.values(DEFAULT_TEZOS_EVENTS);
case "kadena":
return Object.values(DEFAULT_KADENA_EVENTS);
+ case "bip122":
+ return Object.values(DEFAULT_BIP122_EVENTS);
default:
throw new Error(`No default events for namespace: ${namespace}`);
}
diff --git a/advanced/dapps/react-dapp-v2/src/helpers/types.ts b/advanced/dapps/react-dapp-v2/src/helpers/types.ts
index 795318ef2..5c4f54f9f 100644
--- a/advanced/dapps/react-dapp-v2/src/helpers/types.ts
+++ b/advanced/dapps/react-dapp-v2/src/helpers/types.ts
@@ -163,3 +163,15 @@ export interface KadenaAccount {
account: string; // Kadena account
chainId: ChainId; // Kadena ChainId
}
+
+export interface IUTXO {
+ txid: string;
+ vout: number;
+ value: number;
+ status: {
+ confirmed: boolean;
+ block_height: number;
+ block_hash: string;
+ block_time: number;
+ };
+}
diff --git a/advanced/dapps/react-dapp-v2/src/helpers/utilities.ts b/advanced/dapps/react-dapp-v2/src/helpers/utilities.ts
index 776b32c0e..e25fa569d 100644
--- a/advanced/dapps/react-dapp-v2/src/helpers/utilities.ts
+++ b/advanced/dapps/react-dapp-v2/src/helpers/utilities.ts
@@ -182,6 +182,13 @@ export function convertHexToUtf8(hex: string) {
return hex;
}
}
+export function convertHexToBase64(hex: string) {
+ try {
+ return encoding.hexToBuffer(hex).toString("base64");
+ } catch (e) {
+ return hex;
+ }
+}
export const sanitizeDecimals = (value: string, decimals = 18): string => {
const [integer, fractional] = value.split(".");
@@ -196,7 +203,11 @@ export const toWad = (amount: string, decimals = 18): BigNumber => {
};
export const fromWad = (wad: BigNumberish, decimals = 18): string => {
- return sanitizeDecimals(utils.formatUnits(wad, decimals), decimals);
+ try {
+ return sanitizeDecimals(utils.formatUnits(wad, decimals), decimals);
+ } catch (e) {
+ return wad?.toString();
+ }
};
export const LOCALSTORAGE_KEY_TESTNET = "TESTNET";
diff --git a/advanced/dapps/react-dapp-v2/src/pages/index.tsx b/advanced/dapps/react-dapp-v2/src/pages/index.tsx
index 6827e2f7d..b8d844fed 100644
--- a/advanced/dapps/react-dapp-v2/src/pages/index.tsx
+++ b/advanced/dapps/react-dapp-v2/src/pages/index.tsx
@@ -23,6 +23,7 @@ import {
DEFAULT_EIP155_OPTIONAL_METHODS,
DEFAULT_EIP5792_METHODS,
GetCapabilitiesResult,
+ DEFAULT_BIP122_METHODS,
DEFAULT_EIP7715_METHODS,
} from "../constants";
import { AccountAction, setLocaleStorageTestnetFlag } from "../helpers";
@@ -79,6 +80,7 @@ const Home: NextPage = () => {
setChains,
setRelayerRegion,
origin,
+ setAccounts,
} = useWalletConnectClient();
// Use `JsonRpcContext` to provide us with relevant RPC methods and states.
@@ -93,6 +95,7 @@ const Home: NextPage = () => {
tronRpc,
tezosRpc,
kadenaRpc,
+ bip122Rpc,
isRpcRequestPending,
rpcResult,
isTestnet,
@@ -476,6 +479,43 @@ const Home: NextPage = () => {
];
};
+ const getBip122Actions = (): AccountAction[] => {
+ const onSignMessage = async (chainId: string, address: string) => {
+ openRequestModal();
+ await bip122Rpc.testSignMessage(chainId, address);
+ };
+ const onGetAccountAddresses = async (chainId: string, address: string) => {
+ openRequestModal();
+ await bip122Rpc.testGetAccountAddresses(chainId, address);
+ };
+ const onSendTransaction = async (chainId: string, address: string) => {
+ openRequestModal();
+ await bip122Rpc.testSendTransaction(chainId, address);
+ };
+ const onSignPsbt = async (chainId: string, address: string) => {
+ openRequestModal();
+ await bip122Rpc.testSignPsbt(chainId, address);
+ };
+ return [
+ {
+ method: DEFAULT_BIP122_METHODS.BIP122_SEND_TRANSACTION,
+ callback: onSendTransaction,
+ },
+ {
+ method: DEFAULT_BIP122_METHODS.BIP122_GET_ACCOUNT_ADDRESSES,
+ callback: onGetAccountAddresses,
+ },
+ {
+ method: DEFAULT_BIP122_METHODS.BIP122_SIGN_MESSAGE,
+ callback: onSignMessage,
+ },
+ {
+ method: DEFAULT_BIP122_METHODS.BIP122_SIGN_PSBT,
+ callback: onSignPsbt,
+ },
+ ];
+ };
+
const getBlockchainActions = (account: string) => {
const [namespace, chainId, address] = account.split(":");
switch (namespace) {
@@ -497,6 +537,8 @@ const Home: NextPage = () => {
return getTezosActions();
case "kadena":
return getKadenaActions();
+ case "bip122":
+ return getBip122Actions();
default:
break;
}
diff --git a/advanced/dapps/react-dapp-v2/tsconfig.json b/advanced/dapps/react-dapp-v2/tsconfig.json
index 99710e857..bad4c604c 100644
--- a/advanced/dapps/react-dapp-v2/tsconfig.json
+++ b/advanced/dapps/react-dapp-v2/tsconfig.json
@@ -1,6 +1,6 @@
{
"compilerOptions": {
- "target": "es5",
+ "target": "es2015",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
diff --git a/advanced/dapps/react-dapp-v2/yarn.lock b/advanced/dapps/react-dapp-v2/yarn.lock
index 2ead6ccf3..674a5a904 100644
--- a/advanced/dapps/react-dapp-v2/yarn.lock
+++ b/advanced/dapps/react-dapp-v2/yarn.lock
@@ -2367,6 +2367,13 @@
dependencies:
"@noble/hashes" "1.4.0"
+"@noble/curves@^1.6.0":
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.6.0.tgz#be5296ebcd5a1730fccea4786d420f87abfeb40b"
+ integrity sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ==
+ dependencies:
+ "@noble/hashes" "1.5.0"
+
"@noble/ed25519@1.7.3":
version "1.7.3"
resolved "https://registry.yarnpkg.com/@noble/ed25519/-/ed25519-1.7.3.tgz#57e1677bf6885354b466c38e2b620c62f45a7123"
@@ -2392,6 +2399,11 @@
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426"
integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==
+"@noble/hashes@1.5.0":
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.5.0.tgz#abadc5ca20332db2b1b2aa3e496e9af1213570b0"
+ integrity sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==
+
"@noble/hashes@~1.3.0", "@noble/hashes@~1.3.1":
version "1.3.2"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39"
@@ -4967,7 +4979,7 @@ bcrypt-pbkdf@^1.0.0:
dependencies:
tweetnacl "^0.14.3"
-bech32@1.1.4, bech32@^1.1.4:
+bech32@1.1.4, bech32@^1.1.3, bech32@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9"
integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==
@@ -5031,6 +5043,11 @@ bindings@^1.3.0, bindings@^1.5.0:
dependencies:
file-uri-to-path "1.0.0"
+bip174@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/bip174/-/bip174-2.1.1.tgz#ef3e968cf76de234a546962bcf572cc150982f9f"
+ integrity sha512-mdFV5+/v0XyNYXjBS6CQPLo9ekCx4gtKZFnJm5PMto7Fs9hTTDpkkzOB7/FtluRI6JbUUAu+snTYfJRgHLZbZQ==
+
bip39@3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/bip39/-/bip39-3.0.2.tgz#2baf42ff3071fc9ddd5103de92e8f80d9257ee32"
@@ -5048,6 +5065,37 @@ bip39@^3.0.2:
dependencies:
"@noble/hashes" "^1.2.0"
+bip66@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22"
+ integrity sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw==
+ dependencies:
+ safe-buffer "^5.0.1"
+
+bitcoinjs-lib@^6.1.5:
+ version "6.1.6"
+ resolved "https://registry.yarnpkg.com/bitcoinjs-lib/-/bitcoinjs-lib-6.1.6.tgz#f57c17c82511f860f11946d784c18da39f8618a8"
+ integrity sha512-Fk8+Vc+e2rMoDU5gXkW9tD+313rhkm5h6N9HfZxXvYU9LedttVvmXKTgd9k5rsQJjkSfsv6XRM8uhJv94SrvcA==
+ dependencies:
+ "@noble/hashes" "^1.2.0"
+ bech32 "^2.0.0"
+ bip174 "^2.1.1"
+ bs58check "^3.0.1"
+ typeforce "^1.11.3"
+ varuint-bitcoin "^1.1.2"
+
+bitcoinjs-message@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/bitcoinjs-message/-/bitcoinjs-message-2.2.0.tgz#8116ec7f447f9889e23030fc15c5286a6ae5503b"
+ integrity sha512-103Wy3xg8Y9o+pdhGP4M3/mtQQuUWs6sPuOp1mYphSUoSMHjHTlkj32K4zxU8qMH0Ckv23emfkGlFWtoWZ7YFA==
+ dependencies:
+ bech32 "^1.1.3"
+ bs58check "^2.1.2"
+ buffer-equals "^1.0.3"
+ create-hash "^1.1.2"
+ secp256k1 "^3.0.1"
+ varuint-bitcoin "^1.0.1"
+
blake2b-wasm@^1.1.0:
version "1.1.7"
resolved "https://registry.yarnpkg.com/blake2b-wasm/-/blake2b-wasm-1.1.7.tgz#e4d075da10068e5d4c3ec1fb9accc4d186c55d81"
@@ -5201,7 +5249,7 @@ browser-process-hrtime@^1.0.0:
resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626"
integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==
-browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.2.0:
+browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6, browserify-aes@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48"
integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==
@@ -5305,6 +5353,14 @@ bs58check@^2.1.2:
create-hash "^1.1.0"
safe-buffer "^5.1.2"
+bs58check@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-3.0.1.tgz#2094d13720a28593de1cba1d8c4e48602fdd841c"
+ integrity sha512-hjuuJvoWEybo7Hn/0xOrczQKKEKD63WguEjlhLExYs2wUBcebDC1jDNK17eEAD2lYfw82d5ASC1d7K3SWszjaQ==
+ dependencies:
+ "@noble/hashes" "^1.2.0"
+ bs58 "^5.0.0"
+
bser@2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05"
@@ -5312,6 +5368,11 @@ bser@2.1.1:
dependencies:
node-int64 "^0.4.0"
+buffer-equals@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/buffer-equals/-/buffer-equals-1.0.4.tgz#0353b54fd07fd9564170671ae6f66b9cf10d27f5"
+ integrity sha512-99MsCq0j5+RhubVEtKQgKaD6EM+UP3xJgIvQqwJ3SOLDUekzxMX1ylXBng+Wa2sh7mGT0W6RUly8ojjr1Tt6nA==
+
buffer-from@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
@@ -6830,6 +6891,15 @@ dotenv@8.2.0:
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a"
integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==
+drbg.js@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b"
+ integrity sha512-F4wZ06PvqxYLFEZKkFxTDcns9oFNk34hvmJSEwdzsxVQ8YI5YaxtACgQatkYgv2VI2CFkUd2Y+xosPQnHv809g==
+ dependencies:
+ browserify-aes "^1.0.6"
+ create-hash "^1.1.2"
+ create-hmac "^1.1.4"
+
duplexer@^0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
@@ -11344,6 +11414,11 @@ nan@^2.12.1:
resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb"
integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==
+nan@^2.14.0:
+ version "2.19.0"
+ resolved "https://registry.yarnpkg.com/nan/-/nan-2.19.0.tgz#bb58122ad55a6c5bc973303908d5b16cfdd5a8c0"
+ integrity sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==
+
nano-json-stream-parser@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f"
@@ -14126,6 +14201,20 @@ scryptsy@2.1.0:
resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-2.1.0.tgz#8d1e8d0c025b58fdd25b6fa9a0dc905ee8faa790"
integrity sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w==
+secp256k1@^3.0.1:
+ version "3.8.0"
+ resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.8.0.tgz#28f59f4b01dbee9575f56a47034b7d2e3b3b352d"
+ integrity sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw==
+ dependencies:
+ bindings "^1.5.0"
+ bip66 "^1.1.5"
+ bn.js "^4.11.8"
+ create-hash "^1.2.0"
+ drbg.js "^1.0.1"
+ elliptic "^6.5.2"
+ nan "^2.14.0"
+ safe-buffer "^5.1.2"
+
secp256k1@^4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303"
@@ -15465,6 +15554,11 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==
+typeforce@^1.11.3:
+ version "1.18.0"
+ resolved "https://registry.yarnpkg.com/typeforce/-/typeforce-1.18.0.tgz#d7416a2c5845e085034d70fcc5b6cc4a90edbfdc"
+ integrity sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==
+
typescript@^4.7.4:
version "4.9.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a"
@@ -15848,6 +15942,13 @@ varint@^5.0.0:
resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4"
integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==
+varuint-bitcoin@^1.0.1, varuint-bitcoin@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz#e76c138249d06138b480d4c5b40ef53693e24e92"
+ integrity sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw==
+ dependencies:
+ safe-buffer "^5.1.1"
+
vary@^1, vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
diff --git a/advanced/wallets/react-wallet-v2/next.config.js b/advanced/wallets/react-wallet-v2/next.config.js
index e1f3bae45..ebacdf340 100644
--- a/advanced/wallets/react-wallet-v2/next.config.js
+++ b/advanced/wallets/react-wallet-v2/next.config.js
@@ -5,7 +5,12 @@ module.exports = {
...config.resolve.fallback,
fs: false
}
-
+ // needed for tiny-secp256k1 package
+ config.experiments.asyncWebAssembly = true
+ config.module.rules.push({
+ test: /\.wasm$/,
+ type: 'webassembly/async'
+ })
return config
},
async headers() {
diff --git a/advanced/wallets/react-wallet-v2/package.json b/advanced/wallets/react-wallet-v2/package.json
index 3e49268e8..bd77bd224 100644
--- a/advanced/wallets/react-wallet-v2/package.json
+++ b/advanced/wallets/react-wallet-v2/package.json
@@ -26,23 +26,28 @@
"@multiversx/sdk-wallet": "4.2.0",
"@near-wallet-selector/wallet-utils": "^8.0.0",
"@nextui-org/react": "1.0.8-beta.5",
+ "@noble/curves": "^1.6.0",
"@polkadot/keyring": "^10.1.2",
"@polkadot/types": "^9.3.3",
+ "@reown/walletkit": "1.0.0",
"@reown/appkit-experimental": "1.1.5",
"@rhinestone/module-sdk": "0.1.25",
"@solana/web3.js": "1.89.2",
"@taquito/signer": "^15.1.0",
"@taquito/taquito": "^15.1.0",
"@types/semver": "^7.5.8",
- "@reown/walletkit": "1.0.0",
"@zerodev/ecdsa-validator": "5.3.0",
"@zerodev/presets": "5.3.0",
"@zerodev/sdk": "5.3.1",
"@zerodev/session-key": "5.4.0",
"@zerodev/weighted-ecdsa-validator": "5.3.0",
+ "bip32": "^4.0.0",
+ "bitcoinjs-lib": "^6.1.5",
+ "bitcoinjs-message": "^2.2.0",
"borsh": "^1.0.0",
"bs58": "6.0.0",
"cosmos-wallet": "1.2.0",
+ "ecpair": "^2.1.0",
"ethers": "5.7.2",
"framer-motion": "6.5.1",
"graphql": "^16.8.2",
@@ -54,7 +59,8 @@
"react-dom": "17.0.2",
"react-hot-toast": "^2.4.1",
"react-qr-reader-es6": "2.2.1-2",
- "solady": "^0.0.234",
+ "solana-wallet": "^1.0.2",
+ "tiny-secp256k1": "^2.2.3",
"tronweb": "^4.4.0",
"valtio": "1.13.2",
"viem": "2.17.8",
@@ -71,4 +77,4 @@
"prettier": "2.6.2",
"typescript": "5.2.2"
}
-}
\ No newline at end of file
+}
diff --git a/advanced/wallets/react-wallet-v2/public/chain-logos/btc-testnet.png b/advanced/wallets/react-wallet-v2/public/chain-logos/btc-testnet.png
new file mode 100644
index 000000000..b991e4b73
Binary files /dev/null and b/advanced/wallets/react-wallet-v2/public/chain-logos/btc-testnet.png differ
diff --git a/advanced/wallets/react-wallet-v2/src/components/Modal.tsx b/advanced/wallets/react-wallet-v2/src/components/Modal.tsx
index f8fba7876..1f81fc8a3 100644
--- a/advanced/wallets/react-wallet-v2/src/components/Modal.tsx
+++ b/advanced/wallets/react-wallet-v2/src/components/Modal.tsx
@@ -18,7 +18,10 @@ import { useSnapshot } from 'valtio'
import { useCallback, useMemo } from 'react'
import LoadingModal from '@/views/LoadingModal'
import SessionAuthenticateModal from '@/views/SessionAuthenticateModal'
+import SessionSignBip122Modal from '@/views/SessionSignBip122Modal'
+import SessionSendTransactionBip122Modal from '@/views/SessionSendTransactionBip122Modal'
import SessionGrantPermissionsModal from '@/views/SessionGrantPermissionsModal'
+import SessionGetBip122AddressesModal from '@/views/SessionGetBip122AddressesModal'
export default function Modal() {
const { open, view } = useSnapshot(ModalStore.state)
@@ -65,6 +68,12 @@ export default function Modal() {
return
case 'SessionAuthenticateModal':
return
+ case 'SessionSignBip122Modal':
+ return
+ case 'SessionGetBip122AddressesModal':
+ return
+ case 'SessionSendTransactionBip122Modal':
+ return
default:
return null
}
diff --git a/advanced/wallets/react-wallet-v2/src/data/Bip122Data.ts b/advanced/wallets/react-wallet-v2/src/data/Bip122Data.ts
new file mode 100644
index 000000000..e5d09f6d6
--- /dev/null
+++ b/advanced/wallets/react-wallet-v2/src/data/Bip122Data.ts
@@ -0,0 +1,60 @@
+/**
+ * Chains
+ */
+export const BIP122_NAMESPACE = 'bip122'
+
+export const BIP122_MAINNET_ID = '000000000019d6689c085ae165831e93'
+export const BIP122_TESTNET_ID = '000000000933ea01ad0ee984209779ba'
+export const BIP122_MAINNET_CAIP2 = `${BIP122_NAMESPACE}:${BIP122_MAINNET_ID}`
+export const BIP122_TESTNET_CAIP2 = `${BIP122_NAMESPACE}:${BIP122_TESTNET_ID}`
+
+export type IBip122ChainId = typeof BIP122_MAINNET_CAIP2 | typeof BIP122_TESTNET_CAIP2
+
+export const BITCOIN_MAINNET = {
+ [BIP122_MAINNET_CAIP2]: {
+ chainId: BIP122_MAINNET_ID,
+ name: 'BTC Mainnet',
+ logo: '/chain-logos/btc-testnet.png',
+ rgb: '107, 111, 147',
+ rpc: '',
+ coinType: '0',
+ caip2: BIP122_MAINNET_CAIP2 as IBip122ChainId,
+ namespace: BIP122_NAMESPACE
+ }
+}
+export const BITCOIN_TESTNET = {
+ [BIP122_TESTNET_CAIP2]: {
+ chainId: BIP122_TESTNET_ID,
+ name: 'BTC Testnet',
+ logo: '/chain-logos/btc-testnet.png',
+ rgb: '247, 147, 25',
+ rpc: '',
+ coinType: '1',
+ caip2: BIP122_TESTNET_CAIP2 as IBip122ChainId,
+ namespace: BIP122_NAMESPACE
+ }
+}
+
+export const BIP122_CHAINS = { ...BITCOIN_MAINNET, ...BITCOIN_TESTNET } as Record<
+ IBip122ChainId,
+ typeof BITCOIN_MAINNET[typeof BIP122_MAINNET_CAIP2] &
+ typeof BITCOIN_TESTNET[typeof BIP122_TESTNET_CAIP2]
+>
+
+/**
+ * Methods
+ */
+export const BIP122_SIGNING_METHODS = {
+ BIP122_SIGN_MESSAGE: 'signMessage',
+ BIP122_GET_ACCOUNT_ADDRESSES: 'getAccountAddresses',
+ BIP122_SEND_TRANSACTION: 'sendTransfer',
+ BIP122_SIGN_PSBT: 'signPsbt'
+}
+
+/**
+ * Events
+ */
+
+export const BIP122_EVENTS = {
+ BIP122_ADDRESSES_CHANGED: 'bip122_addressesChanged'
+}
diff --git a/advanced/wallets/react-wallet-v2/src/data/chainsUtil.ts b/advanced/wallets/react-wallet-v2/src/data/chainsUtil.ts
index 6ebea5fd2..f002f3d8f 100644
--- a/advanced/wallets/react-wallet-v2/src/data/chainsUtil.ts
+++ b/advanced/wallets/react-wallet-v2/src/data/chainsUtil.ts
@@ -1,3 +1,4 @@
+import { BIP122_CHAINS } from './Bip122Data'
import * as viemChains from 'viem/chains'
import { COSMOS_MAINNET_CHAINS } from './COSMOSData'
import { EIP155_CHAINS } from './EIP155Data'
@@ -18,7 +19,8 @@ export const ALL_CHAINS = {
...POLKADOT_CHAINS,
...SOLANA_CHAINS,
...TEZOS_CHAINS,
- ...TRON_CHAINS
+ ...TRON_CHAINS,
+ ...BIP122_CHAINS
}
export function getChainData(chainId?: string) {
diff --git a/advanced/wallets/react-wallet-v2/src/hooks/useInitialization.ts b/advanced/wallets/react-wallet-v2/src/hooks/useInitialization.ts
index f0f56ea3a..2599b7728 100644
--- a/advanced/wallets/react-wallet-v2/src/hooks/useInitialization.ts
+++ b/advanced/wallets/react-wallet-v2/src/hooks/useInitialization.ts
@@ -12,6 +12,7 @@ import { createOrRestoreKadenaWallet } from '@/utils/KadenaWalletUtil'
import { useCallback, useEffect, useRef, useState } from 'react'
import { useSnapshot } from 'valtio'
import useSmartAccounts from './useSmartAccounts'
+import { createOrRestoreBip122Wallet } from '@/utils/Bip122WalletUtil'
export default function useInitialization() {
const [initialized, setInitialized] = useState(false)
@@ -31,6 +32,7 @@ export default function useInitialization() {
const { tronAddresses } = await createOrRestoreTronWallet()
const { tezosAddresses } = await createOrRestoreTezosWallet()
const { kadenaAddresses } = await createOrRestoreKadenaWallet()
+ const { bip122Addresses } = await createOrRestoreBip122Wallet()
await initializeSmartAccounts(eip155Wallets[eip155Addresses[0]].getPrivateKey())
SettingsStore.setEIP155Address(eip155Addresses[0])
@@ -42,6 +44,7 @@ export default function useInitialization() {
SettingsStore.setTronAddress(tronAddresses[0])
SettingsStore.setTezosAddress(tezosAddresses[0])
SettingsStore.setKadenaAddress(kadenaAddresses[0])
+ SettingsStore.setbip122Address(bip122Addresses[0])
await createWalletKit(relayerRegionURL)
setInitialized(true)
} catch (err: unknown) {
diff --git a/advanced/wallets/react-wallet-v2/src/hooks/useWalletConnectEventsManager.ts b/advanced/wallets/react-wallet-v2/src/hooks/useWalletConnectEventsManager.ts
index 4cf2d9665..c7b5821f6 100644
--- a/advanced/wallets/react-wallet-v2/src/hooks/useWalletConnectEventsManager.ts
+++ b/advanced/wallets/react-wallet-v2/src/hooks/useWalletConnectEventsManager.ts
@@ -18,6 +18,7 @@ import { formatJsonRpcError } from '@json-rpc-tools/utils'
import { approveEIP5792Request } from '@/utils/EIP5792RequestHandlerUtils'
import EIP155Lib from '@/lib/EIP155Lib'
import { getWallet } from '@/utils/EIP155WalletUtil'
+import { BIP122_SIGNING_METHODS } from '@/data/Bip122Data'
import { EIP7715_METHOD } from '@/data/EIP7715Data'
import { refreshSessionsList } from '@/pages/wc'
@@ -140,6 +141,16 @@ export default function useWalletConnectEventsManager(initialized: boolean) {
case KADENA_SIGNING_METHODS.KADENA_SIGN:
case KADENA_SIGNING_METHODS.KADENA_QUICKSIGN:
return ModalStore.open('SessionSignKadenaModal', { requestEvent, requestSession })
+ case BIP122_SIGNING_METHODS.BIP122_SIGN_MESSAGE:
+ return ModalStore.open('SessionSignBip122Modal', { requestEvent, requestSession })
+ case BIP122_SIGNING_METHODS.BIP122_GET_ACCOUNT_ADDRESSES:
+ return ModalStore.open('SessionGetBip122AddressesModal', { requestEvent, requestSession })
+ case BIP122_SIGNING_METHODS.BIP122_SIGN_PSBT:
+ case BIP122_SIGNING_METHODS.BIP122_SEND_TRANSACTION:
+ return ModalStore.open('SessionSendTransactionBip122Modal', {
+ requestEvent,
+ requestSession
+ })
default:
return ModalStore.open('SessionUnsuportedMethodModal', { requestEvent, requestSession })
}
diff --git a/advanced/wallets/react-wallet-v2/src/lib/Bip122Lib.ts b/advanced/wallets/react-wallet-v2/src/lib/Bip122Lib.ts
new file mode 100644
index 000000000..eed33445b
--- /dev/null
+++ b/advanced/wallets/react-wallet-v2/src/lib/Bip122Lib.ts
@@ -0,0 +1,439 @@
+import ECPairFactory from 'ecpair'
+import * as bitcoin from 'bitcoinjs-lib'
+import * as ecc from 'tiny-secp256k1'
+import * as bip39 from 'bip39'
+import BIP32Factory, { BIP32Interface } from 'bip32'
+import bitcoinMessage from 'bitcoinjs-message'
+import { schnorr } from '@noble/secp256k1'
+import { BIP122_CHAINS, BIP122_TESTNET_ID, IBip122ChainId } from '@/data/Bip122Data'
+bitcoin.initEccLib(ecc)
+
+const ECPair = ECPairFactory(ecc)
+const bip32 = BIP32Factory(ecc)
+interface IInitArguments {
+ privateKey?: string
+}
+
+interface IUTXO {
+ txid: string
+ vout: number
+ value: number
+ status: {
+ confirmed: boolean
+ block_height: number
+ block_hash: string
+ block_time: number
+ }
+}
+
+interface ICreateTransaction {
+ network: bitcoin.Network
+ recipientAddress: string
+ amount: number
+ changeAddress: string
+ memo?: string
+ utxos: IUTXO[]
+ privateKeyWIF: string
+ feeRate: number
+}
+
+interface IAddressData {
+ address: string
+ path: string
+ publicKey: string
+}
+
+interface IPsbtInput {
+ address: string
+ index: number
+ sighashTypes: number[]
+}
+
+interface ISignPsbt {
+ account: string
+ psbt: string
+ signInputs: IPsbtInput[]
+ broadcast: boolean
+ chainId: IBip122ChainId
+}
+
+const validator = (pubkey: Buffer, msghash: Buffer, signature: Buffer): boolean => {
+ return ECPair.fromPublicKey(pubkey).verify(msghash, signature)
+}
+
+/**
+ * Library
+ */
+export default class Bip122Lib {
+ private account: BIP32Interface
+ private mnemonic: string
+ private addresses = {} as Record>
+ private ordinals = {} as Record>
+ private keys = {} as Record<
+ IBip122ChainId,
+ Map
+ >
+
+ constructor(key?: string) {
+ this.keys = Object.values(BIP122_CHAINS).reduce((acc, chain) => {
+ acc[chain.caip2] = new Map()
+ return acc
+ }, this.keys)
+ this.addresses = Object.values(BIP122_CHAINS).reduce((acc, chain) => {
+ acc[chain.caip2] = new Map()
+ return acc
+ }, this.addresses)
+ this.ordinals = Object.values(BIP122_CHAINS).reduce((acc, chain) => {
+ acc[chain.caip2] = new Map()
+ return acc
+ }, this.ordinals)
+
+ this.mnemonic = key ? key : bip39.generateMnemonic()
+ const seed = bip39.mnemonicToSeedSync(this.mnemonic)
+ const root = bip32.fromSeed(seed)
+ this.account = bip32.fromBase58(root.toBase58())
+ const addressIndex = (localStorage.getItem(`${seed}_index`) || 0) as number
+ this.loadAddresses(addressIndex)
+ }
+
+ static async init({ privateKey }: IInitArguments) {
+ return new Bip122Lib(privateKey)
+ }
+
+ public getAddress(chainId: IBip122ChainId) {
+ return Array.from(this.addresses[chainId].values())[0].address
+ }
+
+ public getOrdinalsAddress(chainId: IBip122ChainId) {
+ return Array.from(this.ordinals[chainId].values())[0].address
+ }
+
+ public getPrivateKey() {
+ return this.mnemonic
+ }
+
+ public getAddresses(chainId: IBip122ChainId, intentions?: string[]) {
+ if (intentions && intentions[0] === 'ordinal') {
+ return this.ordinals[chainId]
+ }
+ return this.addresses[chainId]
+ }
+
+ public async signMessage({
+ message,
+ address,
+ protocol,
+ chainId
+ }: {
+ message: string
+ address: string
+ protocol?: string
+ chainId: IBip122ChainId
+ }) {
+ if (protocol && protocol !== 'ecdsa') {
+ throw new Error(`Supported signing protols: ecdsa, received: ${protocol}`)
+ }
+ const addressData = this.getAddressData(address, chainId)
+ if (!addressData) {
+ throw new Error(`Unkown address: ${address}`)
+ }
+ const keyData = this.keys[chainId].get(address)!
+ var keyPair = ECPair.fromWIF(keyData.wif)
+ var privateKey = keyPair.privateKey!
+
+ let signature
+ if (this.isOrdinal(address, chainId)) {
+ const messageHash = bitcoin.crypto.sha256(Buffer.from(message))
+
+ const sig = await schnorr.sign(messageHash, privateKey)
+ signature = Buffer.from(sig)
+ } else {
+ signature = bitcoinMessage.sign(message, privateKey, keyPair.compressed, {
+ segwitType: 'p2wpkh'
+ })
+ }
+
+ return {
+ signature: signature.toString('hex').replace('0x', ''),
+ address
+ }
+ }
+
+ public async sendTransfer(params: {
+ account: string
+ recipientAddress: string
+ amount: string
+ changeAddress?: string
+ memo?: string
+ chainId: IBip122ChainId
+ }) {
+ const { account, recipientAddress, amount, changeAddress, memo, chainId } = params
+ const satoshis = parseInt(amount)
+
+ const addressData = this.getAddressData(account, chainId)
+ if (!addressData) {
+ throw new Error(`Unkown address: ${account}`)
+ }
+
+ if (satoshis < 0) {
+ throw new Error(`Invalid amount: ${amount}`)
+ }
+
+ const utxos = (await this.getUTXOs(account, chainId)) as IUTXO[]
+ if (!utxos || utxos.length === 0) {
+ throw new Error(`No UTXOs found for address: ${account}`)
+ }
+
+ let utxosValue = 0
+ const utxosToSpend: IUTXO[] = []
+ utxos.forEach(utxo => {
+ utxosValue += utxo.value
+ utxosToSpend.push(utxo)
+ if (utxosValue >= satoshis) {
+ return
+ }
+ })
+
+ const keyData = this.keys[chainId].get(account)!
+ const transaction = await this.createTransaction({
+ network: keyData.network,
+ recipientAddress,
+ amount: satoshis,
+ changeAddress: changeAddress || account,
+ utxos: utxosToSpend,
+ privateKeyWIF: keyData.wif,
+ memo,
+ feeRate: await this.getFeeRate()
+ })
+ return await this.broadcastTransaction(transaction, chainId)
+ }
+
+ async getUTXOs(address: string, chainId: IBip122ChainId): Promise {
+ const isTestnet = this.isTestnet(chainId)
+ // make chain dynamic
+ return await (
+ await fetch(`https://mempool.space${isTestnet ? '/testnet' : ''}/api/address/${address}/utxo`)
+ ).json()
+ }
+
+ async broadcastTransaction(transaction: string, chainId: IBip122ChainId) {
+ const isTestnet = this.isTestnet(chainId)
+ const result = await fetch(`https://mempool.space${isTestnet ? '/testnet' : ''}/api/tx`, {
+ method: 'POST',
+ body: transaction
+ })
+
+ if (result.ok) {
+ return await result.text()
+ }
+ throw new Error('Error broadcasting transaction: ' + (await result.text()))
+ }
+
+ getAvailableBalance(utxos: IUTXO[]) {
+ return utxos.reduce((acc, { value }) => acc + value, 0)
+ }
+
+ private async getFeeRate() {
+ const defaultFeeRate = 2
+ try {
+ const response = await fetch('https://mempool.space/api/v1/fees/recommended')
+ if (response.ok) {
+ const data = await response.json()
+ return parseInt(data?.economyFee ?? defaultFeeRate)
+ }
+ } catch (e) {
+ console.error('Error fetching fee rate', e)
+ }
+ return defaultFeeRate
+ }
+
+ private generateAddress({
+ index,
+ coinType,
+ chainId,
+ change = false,
+ taproot = false
+ }: {
+ index: number
+ coinType: string
+ chainId: IBip122ChainId
+ change?: boolean
+ taproot?: boolean
+ }) {
+ const network = this.getNetwork(coinType)
+ const path = `m/84'/${coinType}'/0'/${change ? 1 : 0}/${index}`
+ const child = this.account.derivePath(path)
+ let address
+ if (taproot) {
+ address = bitcoin.payments.p2tr({
+ pubkey: child.publicKey.slice(1),
+ network
+ }).address!
+ } else {
+ address = bitcoin.payments.p2wpkh({
+ pubkey: child.publicKey,
+ network
+ }).address!
+ }
+ const wif = child.toWIF()
+ this.keys[chainId].set(address, { wif, network })
+ return { address, path, publicKey: child.publicKey.toString('hex') }
+ }
+
+ private loadAddresses(startIndex = 0) {
+ console.log('Loading addresses...')
+ console.log('Keys:', this.keys)
+ console.log('Addresses:', this.addresses)
+ console.log('Ordinals:', this.ordinals)
+ Object.keys(this.keys).forEach(chainId => {
+ const data = BIP122_CHAINS[chainId as IBip122ChainId]
+ const addressesToLoad = startIndex + 20
+
+ for (let i = startIndex; i < addressesToLoad; i++) {
+ const addressParams = {
+ index: i,
+ chainId: data.caip2,
+ coinType: data.coinType
+ }
+ // payment addresses
+ const addressData = this.generateAddress(addressParams)
+ this.addresses[data.caip2].set(addressData.address, addressData)
+ // ordinals
+ const taprootAddress = this.generateAddress({
+ ...addressParams,
+ taproot: true
+ })
+ this.ordinals[data.caip2].set(taprootAddress.address, taprootAddress)
+ }
+ console.log('Loaded addresses:', this.addresses, this.ordinals)
+ })
+ }
+
+ private getNetwork(coinType: string) {
+ if (coinType === '0') {
+ return bitcoin.networks.bitcoin
+ } else if (coinType === '1') {
+ return bitcoin.networks.testnet
+ }
+ throw new Error(`Unsupported coin type: ${coinType}`)
+ }
+
+ private async createTransaction({
+ network,
+ recipientAddress,
+ amount,
+ changeAddress,
+ memo,
+ utxos,
+ privateKeyWIF,
+ feeRate
+ }: ICreateTransaction) {
+ const psbt = new bitcoin.Psbt({ network })
+ const keyPair = ECPair.fromWIF(privateKeyWIF)
+ const payment = bitcoin.payments.p2wpkh({
+ pubkey: keyPair.publicKey,
+ network: bitcoin.networks.testnet
+ })
+
+ utxos.forEach(utxo => {
+ psbt.addInput({
+ hash: utxo.txid,
+ index: utxo.vout,
+ witnessUtxo: {
+ script: Buffer.from(payment.output?.toString('hex')!, 'hex'),
+ value: utxo.value
+ }
+ })
+ })
+
+ psbt.addOutput({
+ address: recipientAddress,
+ value: amount
+ })
+ const change = this.calculateChange(utxos, amount, feeRate)
+
+ if (change > 0) {
+ psbt.addOutput({
+ address: changeAddress,
+ value: change
+ })
+ }
+
+ if (memo) {
+ const data = Buffer.from(memo, 'utf8')
+ const embed = bitcoin.payments.embed({ data: [data] })
+ psbt.addOutput({
+ script: embed.output!,
+ value: 0
+ })
+ }
+
+ psbt.signAllInputs(keyPair)
+
+ psbt.validateSignaturesOfInput(0, validator)
+
+ psbt.finalizeAllInputs()
+
+ const tx = psbt.extractTransaction()
+
+ return tx.toHex()
+ }
+
+ public async signPsbt({ account, psbt, signInputs, broadcast = false, chainId }: ISignPsbt) {
+ const keyData = this.keys[chainId].get(account)!
+ const keyPair = ECPair.fromWIF(keyData.wif)
+ const transaction = bitcoin.Psbt.fromBase64(psbt, { network: keyData.network })
+ signInputs.forEach(({ address, index, sighashTypes }) => {
+ let keyPairToSignWith = keyPair
+ if (address !== account) {
+ const keyData = this.keys[chainId].get(address)!
+ keyPairToSignWith = ECPair.fromWIF(keyData.wif)
+ }
+ transaction.signInput(index, keyPairToSignWith, sighashTypes)
+ })
+ transaction.validateSignaturesOfInput(0, validator)
+ transaction.finalizeAllInputs()
+
+ if (!broadcast) {
+ return {
+ psbt: transaction.toBase64()
+ }
+ }
+
+ const tx = transaction.extractTransaction()
+ const txId = await this.broadcastTransaction(tx.toHex(), chainId)
+ return {
+ psbt: transaction.toBase64(),
+ txid: txId
+ }
+ }
+
+ // Helper function to calculate change
+ private calculateChange(utxos: IUTXO[], amount: number, feeRate: number): number {
+ const inputSum = utxos.reduce((sum, utxo) => sum + utxo.value, 0)
+ /**
+ * 10 bytes: This is an estimated fixed overhead for the transaction.
+ * 148 bytes: This is the average size of each input (UTXO).
+ * 34 bytes: This is the size of each output.
+ * The multiplication by 2 indicates that there are usually two outputs in a typical transaction (one for the recipient and one for change)
+ */
+ const estimatedSize = 10 + 148 * utxos.length + 34 * 2
+ const fee = estimatedSize * feeRate
+ const change = inputSum - amount - fee
+ return change
+ }
+
+ private getAddressData(address: string, chainId: IBip122ChainId) {
+ const addressData = this.addresses[chainId].get(address)
+ if (addressData) return addressData
+ return this.ordinals[chainId].get(address)
+ }
+
+ private isOrdinal(address: string, chainId: IBip122ChainId) {
+ return this.ordinals[chainId].has(address)
+ }
+
+ private isTestnet(chainId: IBip122ChainId) {
+ return chainId.includes(BIP122_TESTNET_ID)
+ }
+}
diff --git a/advanced/wallets/react-wallet-v2/src/pages/index.tsx b/advanced/wallets/react-wallet-v2/src/pages/index.tsx
index 48346431e..5442640fa 100644
--- a/advanced/wallets/react-wallet-v2/src/pages/index.tsx
+++ b/advanced/wallets/react-wallet-v2/src/pages/index.tsx
@@ -15,6 +15,7 @@ import { Text } from '@nextui-org/react'
import { Fragment } from 'react'
import { useSnapshot } from 'valtio'
import useSmartAccounts from '@/hooks/useSmartAccounts'
+import { BIP122_CHAINS } from '@/data/Bip122Data'
import { useRouter } from 'next/router'
import ChainAbstractionBalanceCard from '@/components/ChainAbstractionBalanceCard'
@@ -30,6 +31,7 @@ export default function HomePage() {
tronAddress,
tezosAddress,
kadenaAddress,
+ bip122Address,
smartAccountEnabled,
chainAbstractionEnabled
} = useSnapshot(SettingsStore.state)
@@ -132,6 +134,17 @@ export default function HomePage() {
data-testid={'chain-card-' + caip10.toString()}
/>
))}
+ {Object.entries(BIP122_CHAINS).map(([caip10, { name, logo, rgb }]) => (
+
+ ))}
{testNets ? (
diff --git a/advanced/wallets/react-wallet-v2/src/store/ModalStore.ts b/advanced/wallets/react-wallet-v2/src/store/ModalStore.ts
index 909c34a35..3b0b6bed6 100644
--- a/advanced/wallets/react-wallet-v2/src/store/ModalStore.ts
+++ b/advanced/wallets/react-wallet-v2/src/store/ModalStore.ts
@@ -33,6 +33,9 @@ interface State {
| 'SessionSignKadenaModal'
| 'SessionAuthenticateModal'
| 'LoadingModal'
+ | 'SessionSignBip122Modal'
+ | 'SessionGetBip122AddressesModal'
+ | 'SessionSendTransactionBip122Modal'
data?: ModalData
}
diff --git a/advanced/wallets/react-wallet-v2/src/store/SettingsStore.ts b/advanced/wallets/react-wallet-v2/src/store/SettingsStore.ts
index 6d70cbb06..706cc9fe8 100644
--- a/advanced/wallets/react-wallet-v2/src/store/SettingsStore.ts
+++ b/advanced/wallets/react-wallet-v2/src/store/SettingsStore.ts
@@ -31,6 +31,7 @@ interface State {
tronAddress: string
tezosAddress: string
kadenaAddress: string
+ bip122Address: string
kernelSmartAccountAddress: string
safeSmartAccountAddress: string
biconomySmartAccountAddress: string
@@ -66,6 +67,7 @@ const state = proxy({
tronAddress: '',
tezosAddress: '',
kadenaAddress: '',
+ bip122Address: '',
kernelSmartAccountAddress: '',
safeSmartAccountAddress: '',
biconomySmartAccountAddress: '',
@@ -127,6 +129,9 @@ const SettingsStore = {
setKadenaAddress(kadenaAddress: string) {
state.kadenaAddress = kadenaAddress
},
+ setbip122Address(bip122Address: string) {
+ state.bip122Address = bip122Address
+ },
setRelayerRegionURL(relayerRegionURL: string) {
state.relayerRegionURL = relayerRegionURL
},
diff --git a/advanced/wallets/react-wallet-v2/src/utils/Bip122RequestHandlerUtil.ts b/advanced/wallets/react-wallet-v2/src/utils/Bip122RequestHandlerUtil.ts
new file mode 100644
index 000000000..1323b35dd
--- /dev/null
+++ b/advanced/wallets/react-wallet-v2/src/utils/Bip122RequestHandlerUtil.ts
@@ -0,0 +1,92 @@
+import { KADENA_SIGNING_METHODS } from '@/data/KadenaData'
+import { formatJsonRpcError, formatJsonRpcResult } from '@json-rpc-tools/utils'
+import { SignClientTypes } from '@walletconnect/types'
+import { getSdkError } from '@walletconnect/utils'
+import { getWalletAddressFromParams } from './HelperUtil'
+import { BIP122_SIGNING_METHODS, IBip122ChainId } from '@/data/Bip122Data'
+import { bip122Addresses, bip122Wallet } from './Bip122WalletUtil'
+
+export async function approveBip122Request(
+ requestEvent: SignClientTypes.EventArguments['session_request']
+) {
+ const { params, id } = requestEvent
+ const { request } = params
+ const chainId = params.chainId as IBip122ChainId
+ const account = request.params.account
+ const wallet = bip122Wallet
+ console.log('wallet:', wallet, bip122Wallet)
+ console.log('account:', account)
+ console.log('request:', request.method)
+ switch (request.method) {
+ case BIP122_SIGNING_METHODS.BIP122_SIGN_MESSAGE:
+ const message = request.params.message
+ const address = request.params.address
+ const protocol = request.params.protocol
+ console.log(
+ 'signing message:',
+ message,
+ 'with address:',
+ address || account,
+ 'chainId:',
+ params
+ )
+ const signature = await wallet.signMessage({
+ message,
+ address: address || account,
+ protocol,
+ chainId
+ })
+ return formatJsonRpcResult(id, signature)
+ case BIP122_SIGNING_METHODS.BIP122_SEND_TRANSACTION:
+ const transactionParams = request.params
+ console.log('signing transaction:', transactionParams, 'with account:', account)
+ const txid = await wallet.sendTransfer({
+ account: transactionParams.account,
+ recipientAddress: transactionParams.recipientAddress,
+ amount: transactionParams.amount,
+ changeAddress: transactionParams.changeAddress,
+ memo: transactionParams.memo,
+ chainId
+ })
+ console.log('signed transaction:', txid)
+ return formatJsonRpcResult(id, { txid })
+ case BIP122_SIGNING_METHODS.BIP122_GET_ACCOUNT_ADDRESSES:
+ console.log('getting addresses for account:', account)
+ const addresses = wallet.getAddresses(chainId)
+ return formatJsonRpcResult(id, Array.from(addresses.values()))
+ case BIP122_SIGNING_METHODS.BIP122_SIGN_PSBT:
+ const psbt = request.params.psbt
+ const signInputs = request.params.signInputs
+ const broadcast = request.params.broadcast
+ console.log(
+ 'signing psbt:',
+ psbt,
+ 'with account:',
+ account,
+ 'inputs:',
+ signInputs,
+ 'broadcast:',
+ broadcast
+ )
+ const result = await wallet.signPsbt({
+ account,
+ psbt,
+ signInputs,
+ broadcast,
+ chainId
+ })
+ console.log('signed psbt:', result)
+ return formatJsonRpcResult(id, result)
+ default:
+ throw new Error(getSdkError('UNSUPPORTED_METHODS').message)
+ }
+}
+
+export function rejectBip122Request(
+ request: SignClientTypes.EventArguments['session_request'],
+ message?: string
+) {
+ const { id } = request
+
+ return formatJsonRpcError(id, message || getSdkError('USER_REJECTED_METHODS').message)
+}
diff --git a/advanced/wallets/react-wallet-v2/src/utils/Bip122WalletUtil.ts b/advanced/wallets/react-wallet-v2/src/utils/Bip122WalletUtil.ts
new file mode 100644
index 000000000..ee1121589
--- /dev/null
+++ b/advanced/wallets/react-wallet-v2/src/utils/Bip122WalletUtil.ts
@@ -0,0 +1,41 @@
+import { BIP122_MAINNET_CAIP2, BIP122_TESTNET_CAIP2 } from '@/data/Bip122Data'
+import BitcoinLib from '@/lib/Bip122Lib'
+
+export let wallet1: BitcoinLib
+export let wallet2: BitcoinLib
+export let bip122Wallet: BitcoinLib
+export let bip122Addresses: string[]
+
+/**
+ * Utilities
+ */
+export async function createOrRestoreBip122Wallet() {
+ const privateKey1 = localStorage.getItem('BITCOIN_PRIVATE_KEY_1')
+
+ if (privateKey1) {
+ wallet1 = await BitcoinLib.init({ privateKey: privateKey1 })
+ // wallet2 = await BitcoinLib.init({ privateKey: privateKey2 })
+ } else {
+ wallet1 = await BitcoinLib.init({})
+ // Don't store private keys in local storage in a production project!
+ localStorage.setItem('BITCOIN_PRIVATE_KEY_1', wallet1.getPrivateKey())
+ console.log('BITCOIN_PRIVATE_KEY_1', wallet1.getPrivateKey())
+ }
+
+ const mainnetAddress = wallet1.getAddress(BIP122_MAINNET_CAIP2)
+
+ console.log('address1', { mainnetAddress, privateKey1 }, mainnetAddress)
+
+ bip122Wallet = wallet1
+ bip122Addresses = [
+ `${BIP122_MAINNET_CAIP2}:${wallet1.getAddress(BIP122_MAINNET_CAIP2)}`,
+ `${BIP122_MAINNET_CAIP2}:${wallet1.getOrdinalsAddress(BIP122_MAINNET_CAIP2)}`,
+ `${BIP122_TESTNET_CAIP2}:${wallet1.getAddress(BIP122_TESTNET_CAIP2)}`,
+ `${BIP122_TESTNET_CAIP2}:${wallet1.getOrdinalsAddress(BIP122_TESTNET_CAIP2)}`
+ ]
+
+ return {
+ bip122Wallet,
+ bip122Addresses
+ }
+}
diff --git a/advanced/wallets/react-wallet-v2/src/utils/WalletConnectUtil.ts b/advanced/wallets/react-wallet-v2/src/utils/WalletConnectUtil.ts
index 2f053cb38..539866e5e 100644
--- a/advanced/wallets/react-wallet-v2/src/utils/WalletConnectUtil.ts
+++ b/advanced/wallets/react-wallet-v2/src/utils/WalletConnectUtil.ts
@@ -6,7 +6,7 @@ export async function createWalletKit(relayerRegionURL: string) {
const core = new Core({
projectId: process.env.NEXT_PUBLIC_PROJECT_ID,
relayUrl: relayerRegionURL ?? process.env.NEXT_PUBLIC_RELAY_URL,
- logger: 'trace'
+ logger: 'error'
})
walletkit = await WalletKit.init({
core,
@@ -15,6 +15,9 @@ export async function createWalletKit(relayerRegionURL: string) {
description: 'React Wallet for WalletConnect',
url: 'https://walletconnect.com/',
icons: ['https://avatars.githubusercontent.com/u/37784886']
+ },
+ signConfig: {
+ disableRequestQueue: true
}
})
diff --git a/advanced/wallets/react-wallet-v2/src/views/SessionGetBip122AddressesModal.tsx b/advanced/wallets/react-wallet-v2/src/views/SessionGetBip122AddressesModal.tsx
new file mode 100644
index 000000000..13cf14958
--- /dev/null
+++ b/advanced/wallets/react-wallet-v2/src/views/SessionGetBip122AddressesModal.tsx
@@ -0,0 +1,92 @@
+/* eslint-disable react-hooks/rules-of-hooks */
+import { Col, Divider, Row, Text } from '@nextui-org/react'
+
+import RequestDataCard from '@/components/RequestDataCard'
+import ModalStore from '@/store/ModalStore'
+import { styledToast } from '@/utils/HelperUtil'
+import { walletkit } from '@/utils/WalletConnectUtil'
+import RequestModal from '../components/RequestModal'
+import { useCallback, useState } from 'react'
+import { approveBip122Request, rejectBip122Request } from '@/utils/Bip122RequestHandlerUtil'
+import { bip122Wallet } from '@/utils/Bip122WalletUtil'
+
+export default function SessionGetBip122AddressesModal() {
+ // Get request and wallet data from store
+ const requestEvent = ModalStore.state.data?.requestEvent
+ const requestSession = ModalStore.state.data?.requestSession
+ const [isLoadingApprove, setIsLoadingApprove] = useState(false)
+ const [isLoadingReject, setIsLoadingReject] = useState(false)
+
+ // Ensure request and wallet are defined
+ if (!requestEvent || !requestSession) {
+ return Missing request data
+ }
+
+ const { topic, params } = requestEvent
+ const { request, chainId } = params
+ const account = request.params.account
+ const intentions = request.params.intentions
+ const addresses = bip122Wallet.getAddresses(intentions)
+ // Handle approve action (logic varies based on request method)
+ const onApprove = useCallback(async () => {
+ if (requestEvent) {
+ const response = await approveBip122Request(requestEvent)
+ try {
+ await walletkit.respondSessionRequest({
+ topic,
+ response
+ })
+ } catch (e) {
+ setIsLoadingApprove(false)
+ styledToast((e as Error).message, 'error')
+ return
+ }
+ setIsLoadingApprove(false)
+ ModalStore.close()
+ }
+ }, [requestEvent, topic])
+
+ // Handle reject action
+ const onReject = useCallback(async () => {
+ if (requestEvent) {
+ setIsLoadingReject(true)
+ const response = rejectBip122Request(requestEvent)
+ try {
+ await walletkit.respondSessionRequest({
+ topic,
+ response
+ })
+ } catch (e) {
+ setIsLoadingReject(false)
+ styledToast((e as Error).message, 'error')
+ return
+ }
+ setIsLoadingReject(false)
+ ModalStore.close()
+ }
+ }, [requestEvent, topic])
+
+ return (
+
+ {account && (
+ <>
+
+
+ Addresses for account
+ {account}
+
+
+
+ >
+ )}
+
+
+ )
+}
diff --git a/advanced/wallets/react-wallet-v2/src/views/SessionProposalModal.tsx b/advanced/wallets/react-wallet-v2/src/views/SessionProposalModal.tsx
index 0686dda94..837b5e98d 100644
--- a/advanced/wallets/react-wallet-v2/src/views/SessionProposalModal.tsx
+++ b/advanced/wallets/react-wallet-v2/src/views/SessionProposalModal.tsx
@@ -36,6 +36,13 @@ import usePriorityAccounts from '@/hooks/usePriorityAccounts'
import useSmartAccounts from '@/hooks/useSmartAccounts'
import { EIP5792_METHODS } from '@/data/EIP5792Data'
import { getWalletCapabilities } from '@/utils/EIP5792WalletUtil'
+import { bip122Addresses, bip122Wallet } from '@/utils/Bip122WalletUtil'
+import {
+ BIP122_CHAINS,
+ BIP122_EVENTS,
+ BIP122_SIGNING_METHODS,
+ IBip122ChainId
+} from '@/data/Bip122Data'
import { EIP7715_METHOD } from '@/data/EIP7715Data'
import { useRouter } from 'next/router'
@@ -105,6 +112,11 @@ export default function SessionProposalModal() {
const tronChains = Object.keys(TRON_CHAINS)
const tronMethods = Object.values(TRON_SIGNING_METHODS)
+ // bip122
+ const bip122Chains = Object.keys(BIP122_CHAINS)
+ const bip122Methods = Object.values(BIP122_SIGNING_METHODS)
+ const bip122Events = Object.values(BIP122_EVENTS)
+
return {
eip155: {
chains: eip155Chains,
@@ -181,9 +193,15 @@ export default function SessionProposalModal() {
accounts: tronChains
.map(chain => tronAddresses.map(address => `${chain}:${address}`))
.flat()
+ },
+ bip122: {
+ chains: bip122Chains,
+ methods: bip122Methods,
+ events: bip122Events,
+ accounts: bip122Addresses
}
}
- }, [])
+ }, [addressesToApprove])
console.log('supportedNamespaces', supportedNamespaces, eip155Addresses)
const requestedChains = useMemo(() => {
@@ -238,6 +256,7 @@ export default function SessionProposalModal() {
}, [proposal, supportedChains])
console.log('notSupportedChains', { notSupportedChains, supportedChains })
const getAddress = useCallback((namespace?: string) => {
+ console.log('getAddress', namespace)
if (!namespace) return 'N/A'
switch (namespace) {
case 'eip155':
@@ -258,6 +277,8 @@ export default function SessionProposalModal() {
return tezosAddresses[0]
case 'tron':
return tronAddresses[0]
+ case 'bip122':
+ return bip122Addresses[0]
}
}, [])
@@ -268,7 +289,9 @@ export default function SessionProposalModal() {
proposal: proposal.params,
supportedNamespaces
})
- } catch (e) {}
+ } catch (e) {
+ console.error('Error building approved namespaces', e)
+ }
}, [proposal.params, supportedNamespaces])
const reorderedEip155Accounts = usePriorityAccounts({ namespaces })
@@ -276,6 +299,7 @@ export default function SessionProposalModal() {
// Hanlde approve action, construct session namespace
const onApprove = useCallback(async () => {
+ console.log('onApprove', { proposal, namespaces })
try {
if (proposal && namespaces) {
setIsLoadingApprove(true)
@@ -285,8 +309,19 @@ export default function SessionProposalModal() {
}
//get capabilities for all reorderedEip155Accounts in wallet
const capabilities = getWalletCapabilities(reorderedEip155Accounts)
- const sessionProperties = { capabilities: JSON.stringify(capabilities) }
-
+ let sessionProperties = {
+ capabilities: JSON.stringify(capabilities)
+ } as any
+ if (namespaces.bip122) {
+ const bip122Chain = namespaces.bip122.chains?.[0]!
+ sessionProperties.bip122_getAccountAddresses = JSON.stringify({
+ payment: Array.from(bip122Wallet.getAddresses(bip122Chain as IBip122ChainId).values()),
+ ordinal: Array.from(
+ bip122Wallet.getAddresses(bip122Chain as IBip122ChainId, ['ordinal']).values()
+ )
+ })
+ }
+ console.log('sessionProperties', sessionProperties)
await walletkit.approveSession({
id: proposal.id,
namespaces,
@@ -323,6 +358,7 @@ export default function SessionProposalModal() {
ModalStore.close()
}, [proposal])
console.log('notSupportedChains', notSupportedChains)
+ console.log('supportedChains', supportedChains)
return (
{(supportedChains.length > 0 &&
supportedChains.map((chain, i) => {
+ console.log('chain', chain)
if (!chain) {
return <>>
}
diff --git a/advanced/wallets/react-wallet-v2/src/views/SessionSendTransactionBip122Modal.tsx b/advanced/wallets/react-wallet-v2/src/views/SessionSendTransactionBip122Modal.tsx
new file mode 100644
index 000000000..19d41b83f
--- /dev/null
+++ b/advanced/wallets/react-wallet-v2/src/views/SessionSendTransactionBip122Modal.tsx
@@ -0,0 +1,88 @@
+import { useCallback, useState } from 'react'
+import { Divider, Text } from '@nextui-org/react'
+
+import RequestDataCard from '@/components/RequestDataCard'
+import RequesDetailsCard from '@/components/RequestDetalilsCard'
+import RequestMethodCard from '@/components/RequestMethodCard'
+import ModalStore from '@/store/ModalStore'
+import { styledToast } from '@/utils/HelperUtil'
+import { walletkit } from '@/utils/WalletConnectUtil'
+import RequestModal from '../components/RequestModal'
+import { approveBip122Request, rejectBip122Request } from '@/utils/Bip122RequestHandlerUtil'
+import { JsonRpcResponse } from '@json-rpc-tools/utils'
+
+export default function SessionSendTransactionBip122Modal() {
+ const [isLoadingApprove, setIsLoadingApprove] = useState(false)
+ const [isLoadingReject, setIsLoadingReject] = useState(false)
+
+ // Get request and wallet data from store
+ const requestEvent = ModalStore.state.data?.requestEvent
+ const requestSession = ModalStore.state.data?.requestSession
+
+ const topic = requestEvent?.topic
+ const params = requestEvent?.params
+ const chainId = params?.chainId
+ const request = params?.request
+ const transaction = request?.params
+
+ // Handle reject action
+ const onReject = useCallback(
+ async (rejection?: JsonRpcResponse) => {
+ if (requestEvent && topic) {
+ setIsLoadingReject(true)
+ const response = rejection || rejectBip122Request(requestEvent)
+ try {
+ await walletkit.respondSessionRequest({
+ topic,
+ response
+ })
+ } catch (e) {
+ setIsLoadingReject(false)
+ styledToast((e as Error).message, 'error')
+ return
+ }
+ setIsLoadingReject(false)
+ ModalStore.close()
+ }
+ },
+ [requestEvent, topic]
+ )
+ // Handle approve action
+ const onApprove = useCallback(async () => {
+ if (requestEvent && topic) {
+ setIsLoadingApprove(true)
+ try {
+ const response = await approveBip122Request(requestEvent)
+ await walletkit.respondSessionRequest({
+ topic,
+ response
+ })
+ } catch (e) {
+ setIsLoadingApprove(false)
+ styledToast((e as Error).message, 'error')
+ onReject(rejectBip122Request(requestEvent, (e as Error).message))
+ }
+ setIsLoadingApprove(false)
+ ModalStore.close()
+ }
+ }, [onReject, requestEvent, topic])
+
+ return request && requestSession ? (
+
+
+
+
+
+
+
+ ) : (
+ Request not found
+ )
+}
diff --git a/advanced/wallets/react-wallet-v2/src/views/SessionSignBip122Modal.tsx b/advanced/wallets/react-wallet-v2/src/views/SessionSignBip122Modal.tsx
new file mode 100644
index 000000000..9cb899b46
--- /dev/null
+++ b/advanced/wallets/react-wallet-v2/src/views/SessionSignBip122Modal.tsx
@@ -0,0 +1,98 @@
+/* eslint-disable react-hooks/rules-of-hooks */
+import { Col, Divider, Row, Text } from '@nextui-org/react'
+
+import RequestDataCard from '@/components/RequestDataCard'
+import RequestDetailsCard from '@/components/RequestDetalilsCard'
+import ModalStore from '@/store/ModalStore'
+import { styledToast } from '@/utils/HelperUtil'
+import { walletkit } from '@/utils/WalletConnectUtil'
+import RequestModal from '../components/RequestModal'
+import { useCallback, useState } from 'react'
+import { approveBip122Request, rejectBip122Request } from '@/utils/Bip122RequestHandlerUtil'
+
+export default function SessionSignBip122Modal() {
+ // Get request and wallet data from store
+ const requestEvent = ModalStore.state.data?.requestEvent
+ const requestSession = ModalStore.state.data?.requestSession
+ const [isLoadingApprove, setIsLoadingApprove] = useState(false)
+ const [isLoadingReject, setIsLoadingReject] = useState(false)
+
+ // Ensure request and wallet are defined
+ if (!requestEvent || !requestSession) {
+ return Missing request data
+ }
+
+ const { topic, params } = requestEvent
+ const { request, chainId } = params
+ const message = request.params.message
+ const account = request.params.account
+ const address = request.params.address
+ // Handle approve action (logic varies based on request method)
+ const onApprove = useCallback(async () => {
+ if (requestEvent) {
+ const response = await approveBip122Request(requestEvent)
+ try {
+ await walletkit.respondSessionRequest({
+ topic,
+ response
+ })
+ } catch (e) {
+ setIsLoadingApprove(false)
+ styledToast((e as Error).message, 'error')
+ return
+ }
+ setIsLoadingApprove(false)
+ ModalStore.close()
+ }
+ }, [requestEvent, topic])
+
+ // Handle reject action
+ const onReject = useCallback(async () => {
+ if (requestEvent) {
+ setIsLoadingReject(true)
+ const response = rejectBip122Request(requestEvent)
+ try {
+ await walletkit.respondSessionRequest({
+ topic,
+ response
+ })
+ } catch (e) {
+ setIsLoadingReject(false)
+ styledToast((e as Error).message, 'error')
+ return
+ }
+ setIsLoadingReject(false)
+ ModalStore.close()
+ }
+ }, [requestEvent, topic])
+
+ return (
+
+
+ {message && (
+ <>
+
+
+ Message
+ {message}
+
+
+
+
+
+ To sign with address
+ {address || account}
+
+
+ >
+ )}
+
+ )
+}
diff --git a/advanced/wallets/react-wallet-v2/yarn.lock b/advanced/wallets/react-wallet-v2/yarn.lock
index a8951305c..65c44d161 100644
--- a/advanced/wallets/react-wallet-v2/yarn.lock
+++ b/advanced/wallets/react-wallet-v2/yarn.lock
@@ -87,6 +87,13 @@
dependencies:
regenerator-runtime "^0.14.0"
+"@babel/runtime@^7.25.0":
+ version "7.26.0"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1"
+ integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==
+ dependencies:
+ regenerator-runtime "^0.14.0"
+
"@babel/runtime@^7.6.2":
version "7.24.7"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.7.tgz#f4f0d5530e8dbdf59b3451b9b3e594b6ba082e12"
@@ -1266,7 +1273,7 @@
dependencies:
"@noble/hashes" "1.4.0"
-"@noble/curves@1.6.0", "@noble/curves@~1.6.0":
+"@noble/curves@1.6.0", "@noble/curves@^1.4.2", "@noble/curves@^1.6.0", "@noble/curves@~1.6.0":
version "1.6.0"
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.6.0.tgz#be5296ebcd5a1730fccea4786d420f87abfeb40b"
integrity sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ==
@@ -2255,6 +2262,11 @@
resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938"
integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==
+"@scure/base@^1.1.1", "@scure/base@~1.1.7", "@scure/base@~1.1.8":
+ version "1.1.9"
+ resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.9.tgz#e5e142fbbfe251091f9c5f1dd4c834ac04c3dbd1"
+ integrity sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==
+
"@scure/base@~1.1.4":
version "1.1.5"
resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.5.tgz#1d85d17269fe97694b9c592552dd9e5e33552157"
@@ -2265,11 +2277,6 @@
resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.7.tgz#fe973311a5c6267846aa131bc72e96c5d40d2b30"
integrity sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g==
-"@scure/base@~1.1.7", "@scure/base@~1.1.8":
- version "1.1.9"
- resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.9.tgz#e5e142fbbfe251091f9c5f1dd4c834ac04c3dbd1"
- integrity sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==
-
"@scure/bip32@1.3.3":
version "1.3.3"
resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.3.tgz#a9624991dc8767087c57999a5d79488f48eae6c8"
@@ -2349,6 +2356,27 @@
rpc-websockets "^7.5.1"
superstruct "^0.14.2"
+"@solana/web3.js@^1.66.2":
+ version "1.95.4"
+ resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.95.4.tgz#771603f60d75cf7556ad867e1fd2efae32f9ad09"
+ integrity sha512-sdewnNEA42ZSMxqkzdwEWi6fDgzwtJHaQa5ndUGEJYtoOnM6X5cvPmjoTUp7/k7bRrVAxfBgDnvQQHD6yhlLYw==
+ dependencies:
+ "@babel/runtime" "^7.25.0"
+ "@noble/curves" "^1.4.2"
+ "@noble/hashes" "^1.4.0"
+ "@solana/buffer-layout" "^4.0.1"
+ agentkeepalive "^4.5.0"
+ bigint-buffer "^1.1.5"
+ bn.js "^5.2.1"
+ borsh "^0.7.0"
+ bs58 "^4.0.1"
+ buffer "6.0.3"
+ fast-stable-stringify "^1.0.0"
+ jayson "^4.1.1"
+ node-fetch "^2.7.0"
+ rpc-websockets "^9.0.2"
+ superstruct "^2.0.2"
+
"@stablelib/aead@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@stablelib/aead/-/aead-1.0.1.tgz#c4b1106df9c23d1b867eb9b276d8f42d5fc4c0c3"
@@ -2548,6 +2576,13 @@
dependencies:
tslib "^2.4.0"
+"@swc/helpers@^0.5.11":
+ version "0.5.13"
+ resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.13.tgz#33e63ff3cd0cade557672bd7888a39ce7d115a8c"
+ integrity sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==
+ dependencies:
+ tslib "^2.4.0"
+
"@taquito/http-utils@^15.1.0":
version "15.1.0"
resolved "https://registry.yarnpkg.com/@taquito/http-utils/-/http-utils-15.1.0.tgz#66f3ce220c483e33d6b31bca6e0c76b5b895ed9b"
@@ -2773,6 +2808,11 @@
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.10.tgz#04ffa7f406ab628f7f7e97ca23e290cd8ab15efc"
integrity sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==
+"@types/uuid@^8.3.4":
+ version "8.3.4"
+ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc"
+ integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==
+
"@types/ws@^7.4.4":
version "7.4.7"
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702"
@@ -2780,6 +2820,13 @@
dependencies:
"@types/node" "*"
+"@types/ws@^8.2.2":
+ version "8.5.12"
+ resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.12.tgz#619475fe98f35ccca2a2f6c137702d85ec247b7e"
+ integrity sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==
+ dependencies:
+ "@types/node" "*"
+
"@typescript-eslint/parser@^5.21.0":
version "5.62.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.62.0.tgz#1b63d082d849a2fcae8a569248fbe2ee1b8a56c7"
@@ -3416,6 +3463,11 @@ base-x@^3.0.2:
dependencies:
safe-buffer "^5.0.1"
+base-x@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.0.tgz#d0e3b7753450c73f8ad2389b5c018a4af7b2224a"
+ integrity sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==
+
base-x@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/base-x/-/base-x-5.0.0.tgz#6d835ceae379130e1a4cb846a70ac4746f28ea9b"
@@ -3426,7 +3478,7 @@ base64-js@^1.3.0, base64-js@^1.3.1:
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
-bech32@1.1.4, bech32@^1.1.4:
+bech32@1.1.4, bech32@^1.1.3, bech32@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9"
integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==
@@ -3458,13 +3510,28 @@ binary-extensions@^2.0.0:
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
-bindings@^1.3.0:
+bindings@^1.3.0, bindings@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==
dependencies:
file-uri-to-path "1.0.0"
+bip174@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/bip174/-/bip174-2.1.1.tgz#ef3e968cf76de234a546962bcf572cc150982f9f"
+ integrity sha512-mdFV5+/v0XyNYXjBS6CQPLo9ekCx4gtKZFnJm5PMto7Fs9hTTDpkkzOB7/FtluRI6JbUUAu+snTYfJRgHLZbZQ==
+
+bip32@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/bip32/-/bip32-4.0.0.tgz#7fac3c05072188d2d355a4d6596b37188f06aa2f"
+ integrity sha512-aOGy88DDlVUhspIXJN+dVEtclhIsfAUppD43V0j40cPTld3pv/0X/MlrZSZ6jowIaQQzFwP8M6rFU2z2mVYjDQ==
+ dependencies:
+ "@noble/hashes" "^1.2.0"
+ "@scure/base" "^1.1.1"
+ typeforce "^1.11.5"
+ wif "^2.0.6"
+
bip39@3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/bip39/-/bip39-3.0.2.tgz#2baf42ff3071fc9ddd5103de92e8f80d9257ee32"
@@ -3482,6 +3549,37 @@ bip39@^3.0.2, bip39@^3.0.4:
dependencies:
"@noble/hashes" "^1.2.0"
+bip66@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22"
+ integrity sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw==
+ dependencies:
+ safe-buffer "^5.0.1"
+
+bitcoinjs-lib@^6.1.5:
+ version "6.1.6"
+ resolved "https://registry.yarnpkg.com/bitcoinjs-lib/-/bitcoinjs-lib-6.1.6.tgz#f57c17c82511f860f11946d784c18da39f8618a8"
+ integrity sha512-Fk8+Vc+e2rMoDU5gXkW9tD+313rhkm5h6N9HfZxXvYU9LedttVvmXKTgd9k5rsQJjkSfsv6XRM8uhJv94SrvcA==
+ dependencies:
+ "@noble/hashes" "^1.2.0"
+ bech32 "^2.0.0"
+ bip174 "^2.1.1"
+ bs58check "^3.0.1"
+ typeforce "^1.11.3"
+ varuint-bitcoin "^1.1.2"
+
+bitcoinjs-message@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/bitcoinjs-message/-/bitcoinjs-message-2.2.0.tgz#8116ec7f447f9889e23030fc15c5286a6ae5503b"
+ integrity sha512-103Wy3xg8Y9o+pdhGP4M3/mtQQuUWs6sPuOp1mYphSUoSMHjHTlkj32K4zxU8qMH0Ckv23emfkGlFWtoWZ7YFA==
+ dependencies:
+ bech32 "^1.1.3"
+ bs58check "^2.1.2"
+ buffer-equals "^1.0.3"
+ create-hash "^1.1.2"
+ secp256k1 "^3.0.1"
+ varuint-bitcoin "^1.0.1"
+
blake2b-wasm@^1.1.0:
version "1.1.7"
resolved "https://registry.yarnpkg.com/blake2b-wasm/-/blake2b-wasm-1.1.7.tgz#e4d075da10068e5d4c3ec1fb9accc4d186c55d81"
@@ -3556,6 +3654,18 @@ brorand@^1.1.0:
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==
+browserify-aes@^1.0.6:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48"
+ integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==
+ dependencies:
+ buffer-xor "^1.0.3"
+ cipher-base "^1.0.0"
+ create-hash "^1.1.0"
+ evp_bytestokey "^1.0.3"
+ inherits "^2.0.1"
+ safe-buffer "^5.0.1"
+
bs58@6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/bs58/-/bs58-6.0.0.tgz#a2cda0130558535dd281a2f8697df79caaf425d8"
@@ -3570,7 +3680,14 @@ bs58@^4.0.0, bs58@^4.0.1:
dependencies:
base-x "^3.0.2"
-bs58check@^2.1.2:
+bs58@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/bs58/-/bs58-5.0.0.tgz#865575b4d13c09ea2a84622df6c8cbeb54ffc279"
+ integrity sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==
+ dependencies:
+ base-x "^4.0.0"
+
+bs58check@<3.0.0, bs58check@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc"
integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==
@@ -3579,11 +3696,29 @@ bs58check@^2.1.2:
create-hash "^1.1.0"
safe-buffer "^5.1.2"
+bs58check@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-3.0.1.tgz#2094d13720a28593de1cba1d8c4e48602fdd841c"
+ integrity sha512-hjuuJvoWEybo7Hn/0xOrczQKKEKD63WguEjlhLExYs2wUBcebDC1jDNK17eEAD2lYfw82d5ASC1d7K3SWszjaQ==
+ dependencies:
+ "@noble/hashes" "^1.2.0"
+ bs58 "^5.0.0"
+
+buffer-equals@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/buffer-equals/-/buffer-equals-1.0.4.tgz#0353b54fd07fd9564170671ae6f66b9cf10d27f5"
+ integrity sha512-99MsCq0j5+RhubVEtKQgKaD6EM+UP3xJgIvQqwJ3SOLDUekzxMX1ylXBng+Wa2sh7mGT0W6RUly8ojjr1Tt6nA==
+
buffer-reverse@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/buffer-reverse/-/buffer-reverse-1.0.1.tgz#49283c8efa6f901bc01fa3304d06027971ae2f60"
integrity sha512-M87YIUBsZ6N924W57vDwT/aOu8hw7ZgdByz6ijksLjmHJELBASmYTTlNHRgjE+pTsT9oJXGaDSgqqwfdHotDUg==
+buffer-xor@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
+ integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==
+
buffer@6.0.3, buffer@^6.0.3, buffer@~6.0.3:
version "6.0.3"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
@@ -3680,7 +3815,7 @@ chokidar@^3.5.3:
optionalDependencies:
fsevents "~2.3.2"
-cipher-base@^1.0.1, cipher-base@^1.0.3:
+cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==
@@ -3818,7 +3953,7 @@ cosmos-wallet@1.2.0:
"@cosmjs/amino" "^0.25.4"
"@cosmjs/proto-signing" "^0.25.4"
-create-hash@^1.1.0, create-hash@^1.1.2:
+create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==
@@ -4055,6 +4190,15 @@ dom-helpers@^5.0.1:
"@babel/runtime" "^7.8.7"
csstype "^3.0.2"
+drbg.js@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b"
+ integrity sha512-F4wZ06PvqxYLFEZKkFxTDcns9oFNk34hvmJSEwdzsxVQ8YI5YaxtACgQatkYgv2VI2CFkUd2Y+xosPQnHv809g==
+ dependencies:
+ browserify-aes "^1.0.6"
+ create-hash "^1.1.2"
+ create-hmac "^1.1.4"
+
duplexify@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0"
@@ -4065,6 +4209,15 @@ duplexify@^4.1.2:
readable-stream "^3.1.1"
stream-shift "^1.0.0"
+ecpair@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/ecpair/-/ecpair-2.1.0.tgz#673f826b1d80d5eb091b8e2010c6b588e8d2cb45"
+ integrity sha512-cL/mh3MtJutFOvFc27GPZE2pWL3a3k4YvzUWEOvilnfZVlH3Jwgx/7d6tlD7/75tNk8TG2m+7Kgtz0SI1tWcqw==
+ dependencies:
+ randombytes "^2.1.0"
+ typeforce "^1.18.0"
+ wif "^2.0.6"
+
ed25519-hd-key@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/ed25519-hd-key/-/ed25519-hd-key-1.1.2.tgz#168dcf08419694be7bba3319e7d64e4a5cfe5d44"
@@ -4559,11 +4712,24 @@ eventemitter3@^4.0.7:
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
+eventemitter3@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4"
+ integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==
+
events@3.3.0, events@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
+evp_bytestokey@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02"
+ integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==
+ dependencies:
+ md5.js "^1.3.4"
+ safe-buffer "^5.1.1"
+
execa@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
@@ -5432,6 +5598,24 @@ jayson@^4.1.0:
uuid "^8.3.2"
ws "^7.4.5"
+jayson@^4.1.1:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/jayson/-/jayson-4.1.2.tgz#443c26a8658703e0b2e881117b09395d88b6982e"
+ integrity sha512-5nzMWDHy6f+koZOuYsArh2AXs73NfWYVlFyJJuCedr93GpY+Ku8qq10ropSXVfHK+H0T6paA88ww+/dV+1fBNA==
+ dependencies:
+ "@types/connect" "^3.4.33"
+ "@types/node" "^12.12.54"
+ "@types/ws" "^7.4.4"
+ JSONStream "^1.3.5"
+ commander "^2.20.3"
+ delay "^5.0.0"
+ es6-promisify "^5.0.0"
+ eyes "^0.1.8"
+ isomorphic-ws "^4.0.1"
+ json-stringify-safe "^5.0.1"
+ uuid "^8.3.2"
+ ws "^7.5.10"
+
jiti@^1.20.0:
version "1.21.0"
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d"
@@ -5925,6 +6109,11 @@ mustache@^4.0.0:
resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64"
integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==
+nan@^2.14.0:
+ version "2.22.0"
+ resolved "https://registry.yarnpkg.com/nan/-/nan-2.22.0.tgz#31bc433fc33213c97bad36404bb68063de604de3"
+ integrity sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==
+
nanoassert@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/nanoassert/-/nanoassert-1.1.0.tgz#4f3152e09540fde28c76f44b19bbcd1d5a42478d"
@@ -6722,6 +6911,22 @@ rpc-websockets@^7.5.1:
bufferutil "^4.0.1"
utf-8-validate "^5.0.2"
+rpc-websockets@^9.0.2:
+ version "9.0.4"
+ resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-9.0.4.tgz#9d8ee82533b5d1e13d9ded729e3e38d0d8fa083f"
+ integrity sha512-yWZWN0M+bivtoNLnaDbtny4XchdAIF5Q4g/ZsC5UC61Ckbp0QczwO8fg44rV3uYmY4WHd+EZQbn90W1d8ojzqQ==
+ dependencies:
+ "@swc/helpers" "^0.5.11"
+ "@types/uuid" "^8.3.4"
+ "@types/ws" "^8.2.2"
+ buffer "^6.0.3"
+ eventemitter3 "^5.0.1"
+ uuid "^8.3.2"
+ ws "^8.5.0"
+ optionalDependencies:
+ bufferutil "^4.0.1"
+ utf-8-validate "^5.0.2"
+
run-parallel@^1.1.9:
version "1.2.0"
resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
@@ -6753,7 +6958,7 @@ safe-array-concat@^1.0.1:
has-symbols "^1.0.3"
isarray "^2.0.5"
-safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
+safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
@@ -6790,6 +6995,20 @@ scryptsy@2.1.0:
resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-2.1.0.tgz#8d1e8d0c025b58fdd25b6fa9a0dc905ee8faa790"
integrity sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w==
+secp256k1@^3.0.1:
+ version "3.8.1"
+ resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.8.1.tgz#b62a62a882d6b16f9b51fe599c6b3a861e36c59f"
+ integrity sha512-tArjQw2P0RTdY7QmkNehgp6TVvQXq6ulIhxv8gaH6YubKG/wxxAoNKcbuXjDhybbc+b2Ihc7e0xxiGN744UIiQ==
+ dependencies:
+ bindings "^1.5.0"
+ bip66 "^1.1.5"
+ bn.js "^4.11.8"
+ create-hash "^1.2.0"
+ drbg.js "^1.0.1"
+ elliptic "^6.5.7"
+ nan "^2.14.0"
+ safe-buffer "^5.1.2"
+
semver@^5.6.0:
version "5.7.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
@@ -6892,16 +7111,20 @@ slash@^3.0.0:
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
-solady@^0.0.234:
- version "0.0.234"
- resolved "https://registry.yarnpkg.com/solady/-/solady-0.0.234.tgz#99ddd59e38f1987683b465e5f97d6808c2c50a32"
- integrity sha512-twY/0NtBbOZ7fGFIqp7Ebuvfgw2yD6A44HKbEpS05RK03VH+bv81/Mg6kYI/7EK/NuATlvrACDdLYfp/c1+d4A==
-
solady@^0.0.235:
version "0.0.235"
resolved "https://registry.yarnpkg.com/solady/-/solady-0.0.235.tgz#50ab6e403ed6935012df2c16803fcd58045f9a0e"
integrity sha512-JUEXLDG7ag3HmqUnrDG7ilhafH6R9bFPpwV63O2kH4UbnS2+gRGEOqqy4k01O7tHjo3MWkDD0cpG+UY9pjy/fQ==
+solana-wallet@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/solana-wallet/-/solana-wallet-1.0.2.tgz#1b8157974a0ec5228ac45d8414c656dcb3a94d47"
+ integrity sha512-oZnLJvwBFnQ0Hf0vTuAUFizq59AhxDfoMpdDUuqo02seNsV7AbYl3QGJZBJ1uCr36cRJnXFr2NqI3RM2IDq62Q==
+ dependencies:
+ "@solana/web3.js" "^1.66.2"
+ bs58 "^5.0.0"
+ tweetnacl "^1.0.3"
+
sonic-boom@^2.2.1:
version "2.8.0"
resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-2.8.0.tgz#c1def62a77425090e6ad7516aad8eb402e047611"
@@ -7111,6 +7334,11 @@ superstruct@^0.14.2:
resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-0.14.2.tgz#0dbcdf3d83676588828f1cf5ed35cda02f59025b"
integrity sha512-nPewA6m9mR3d6k7WkZ8N8zpTWfenFH3q9pA2PkuiZxINr9DKB2+40wEQf0ixn8VaGuJ78AB6iWOtStI+/4FKZQ==
+superstruct@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-2.0.2.tgz#3f6d32fbdc11c357deff127d591a39b996300c54"
+ integrity sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==
+
supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
@@ -7152,6 +7380,13 @@ thread-stream@^0.15.1:
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
+tiny-secp256k1@^2.2.3:
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/tiny-secp256k1/-/tiny-secp256k1-2.2.3.tgz#fe1dde11a64fcee2091157d4b78bcb300feb9b65"
+ integrity sha512-SGcL07SxcPN2nGKHTCvRMkQLYPSoeFcvArUSCYtjVARiFAWU44cCIqYS0mYAU6nY7XfvwURuTIGo2Omt3ZQr0Q==
+ dependencies:
+ uint8array-tools "0.0.7"
+
tiny-warning@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
@@ -7298,6 +7533,11 @@ typedarray-to-buffer@^4.0.0:
resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-4.0.0.tgz#cdd2933c61dd3f5f02eda5d012d441f95bfeb50a"
integrity sha512-6dOYeZfS3O9RtRD1caom0sMxgK59b27+IwoNy8RDPsmslSGOyU+mpTamlaIW7aNKi90ZQZ9DFaZL3YRoiSCULQ==
+typeforce@^1.11.3, typeforce@^1.11.5, typeforce@^1.18.0:
+ version "1.18.0"
+ resolved "https://registry.yarnpkg.com/typeforce/-/typeforce-1.18.0.tgz#d7416a2c5845e085034d70fcc5b6cc4a90edbfdc"
+ integrity sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==
+
typescript@5.2.2:
version "5.2.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78"
@@ -7313,6 +7553,11 @@ ufo@^1.3.0, ufo@^1.3.1, ufo@^1.3.2:
resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.3.2.tgz#c7d719d0628a1c80c006d2240e0d169f6e3c0496"
integrity sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==
+uint8array-tools@0.0.7:
+ version "0.0.7"
+ resolved "https://registry.yarnpkg.com/uint8array-tools/-/uint8array-tools-0.0.7.tgz#a7a2bb5d8836eae2fade68c771454e6a438b390d"
+ integrity sha512-vrrNZJiusLWoFWBqz5Y5KMCgP9W9hnjZHzZiZRT8oNAkq3d5Z5Oe76jAvVVSRh4U8GGR90N2X1dWtrhvx6L8UQ==
+
uint8arrays@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.1.0.tgz#8186b8eafce68f28bd29bd29d683a311778901e2"
@@ -7455,6 +7700,13 @@ valtio@1.13.2:
proxy-compare "2.6.0"
use-sync-external-store "1.2.0"
+varuint-bitcoin@^1.0.1, varuint-bitcoin@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz#e76c138249d06138b480d4c5b40ef53693e24e92"
+ integrity sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw==
+ dependencies:
+ safe-buffer "^5.1.1"
+
viem@2.17.8:
version "2.17.8"
resolved "https://registry.yarnpkg.com/viem/-/viem-2.17.8.tgz#79da50ef86fb429d3b36d4ef2f49be5b2999420f"
@@ -7589,6 +7841,13 @@ which@^2.0.1:
dependencies:
isexe "^2.0.0"
+wif@^2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/wif/-/wif-2.0.6.tgz#08d3f52056c66679299726fade0d432ae74b4704"
+ integrity sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==
+ dependencies:
+ bs58check "<3.0.0"
+
wordwrap@~0.0.2:
version "0.0.3"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
@@ -7628,6 +7887,11 @@ ws@^7.4.5, ws@^7.5.1:
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591"
integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==
+ws@^7.5.10:
+ version "7.5.10"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9"
+ integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==
+
ws@^8.5.0:
version "8.15.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.15.1.tgz#271ba33a45ca0cc477940f7f200cd7fba7ee1997"