Skip to content

Commit

Permalink
feat(UTXO Global): switchNetwork
Browse files Browse the repository at this point in the history
  • Loading branch information
Hanssen0 committed Aug 29, 2024
1 parent 44c7fee commit 69c10fd
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 7 deletions.
10 changes: 10 additions & 0 deletions .changeset/heavy-jars-crash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@ckb-ccc/utxo-global": patch
"@ckb-ccc/core": patch
"@ckb-ccc/ccc": patch
"ckb-ccc": patch
"@ckb-ccc/connector": patch
"@ckb-ccc/connector-react": patch
---

feat(utxo-global): switchNetwork
2 changes: 1 addition & 1 deletion packages/ccc/src/signersController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export class SignersController {
await this.addSigners(
"UTXO Global Wallet",
UTXO_GLOBAL_SVG,
UtxoGlobal.getUtxoGlobalSigners(client),
UtxoGlobal.getUtxoGlobalSigners(client, preferredNetworks),
context,
);

Expand Down
6 changes: 4 additions & 2 deletions packages/core/src/signer/signer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ export type NetworkPreference = {
* BTC: // They made a mess...
* btc
* btcTestnet
* btcSignet // OKX
* btcTestnet4 // UTXO Global
* btcSignet // OKX & UTXO Global
* fractalBtc // UniSat
*/
network: string;
Expand Down Expand Up @@ -82,9 +83,10 @@ export abstract class Signer {
// undefined otherwise
matchNetworkPreference(
preferences: NetworkPreference[],
currentNetwork: string,
currentNetwork: string | undefined,
): NetworkPreference | undefined {
if (
currentNetwork !== undefined &&
preferences.some(({ signerType, addressPrefix, network }) => {
signerType === this.type &&
addressPrefix === this.client.addressPrefix &&
Expand Down
8 changes: 6 additions & 2 deletions packages/utxo-global/src/advancedBarrel.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { ccc } from "@ckb-ccc/core";

export interface Provider {
requestAccounts(): Promise<string[]>;
getAccount(): Promise<string[]>;
getPublicKey(): Promise<{ address: string; publicKey: string }[]>;
connect(): Promise<void>;
isConnected(): Promise<boolean>;
signMessage(msg: string, address: string): Promise<string>;
createTx(tx: any): Promise<string>;
signTransaction(tx: any): Promise<any>;
signTransaction(tx: ccc.TransactionLike): Promise<ccc.TransactionLike>;

getNetwork(): Promise<string>;
switchNetwork(network: string): Promise<void>;

on: OnMethod;
removeListener(
Expand Down
79 changes: 79 additions & 0 deletions packages/utxo-global/src/btc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ export class SignerBtc extends ccc.SignerBtc {
constructor(
client: ccc.Client,
public readonly provider: Provider,
private readonly preferredNetworks: ccc.NetworkPreference[] = [
{
addressPrefix: "ckb",
signerType: ccc.SignerType.BTC,
network: "btc",
},
{
addressPrefix: "ckt",
signerType: ccc.SignerType.BTC,
network: "btcTestnet",
},
],
) {
super(client);
}
Expand All @@ -32,11 +44,78 @@ export class SignerBtc extends ccc.SignerBtc {
return ccc.hexFrom(pubKey.publicKey);
}

/**
* Ensure the BTC network is the same as CKB network.
*/
async ensureNetwork(): Promise<void> {
const network = await this._getNetworkToChange();
if (!network) {
return;
}

const chain = {
btc: "btc",
btcTestnet: "btc_testnet",
btcTestnet4: "btc_testnet_4",
btcSignet: "btc_signet",
}[network];

if (chain) {
await this.provider.switchNetwork(chain);
return;
}

throw new Error(
`UTXO Global wallet doesn't support the requested chain ${network}`,
);
}

async _getNetworkToChange(): Promise<string | undefined> {
const currentNetwork = {
btc: "btc",
btc_testnet: "btcTestnet",
btc_testnet_4: "btcTestnet4",
btc_signet: "btcSignet",
}[await this.provider.getNetwork()];

const { network } = this.matchNetworkPreference(
this.preferredNetworks,
currentNetwork,
) ?? { network: currentNetwork };
if (network === currentNetwork) {
return;
}

return network;
}

onReplaced(listener: () => void): () => void {
const stop: (() => void)[] = [];
const replacer = async () => {
listener();
stop[0]?.();
};
stop.push(() => {
this.provider.removeListener("accountsChanged", replacer);
this.provider.removeListener("networkChanged", replacer);
});

this.provider.on("accountsChanged", replacer);
this.provider.on("networkChanged", replacer);

return stop[0];
}

async connect(): Promise<void> {
await this.provider.connect();
await this.ensureNetwork();
}

async isConnected(): Promise<boolean> {
if ((await this._getNetworkToChange()) !== undefined) {
return false;
}

return await this.provider.isConnected();
}

Expand Down
31 changes: 31 additions & 0 deletions packages/utxo-global/src/ckb/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,42 @@ export class SignerCkb extends ccc.Signer {
return ccc.hexFrom(pubKey.publicKey);
}

get ckbNetwork(): string {
return this.client.addressPrefix === "ckb" ? "nervos" : "nervos_testnet";
}

async connect(): Promise<void> {
await this.provider.connect();

if (this.ckbNetwork === (await this.provider.getNetwork())) {
return;
}

await this.provider.switchNetwork(this.ckbNetwork);
}

onReplaced(listener: () => void): () => void {
const stop: (() => void)[] = [];
const replacer = async () => {
listener();
stop[0]?.();
};
stop.push(() => {
this.provider.removeListener("accountsChanged", replacer);
this.provider.removeListener("networkChanged", replacer);
});

this.provider.on("accountsChanged", replacer);
this.provider.on("networkChanged", replacer);

return stop[0];
}

async isConnected(): Promise<boolean> {
if ((await this.provider.getNetwork()) !== this.ckbNetwork) {
return false;
}

return await this.provider.isConnected();
}

Expand Down
11 changes: 9 additions & 2 deletions packages/utxo-global/src/signersFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import { SignerCkb } from "./ckb/index.js";
/**
* @public
*/
export function getUtxoGlobalSigners(client: ccc.Client): ccc.SignerInfo[] {
export function getUtxoGlobalSigners(
client: ccc.Client,
preferredNetworks?: ccc.NetworkPreference[],
): ccc.SignerInfo[] {
const windowRef = window as {
utxoGlobal?: {
bitcoinSigner: Provider;
Expand All @@ -25,7 +28,11 @@ export function getUtxoGlobalSigners(client: ccc.Client): ccc.SignerInfo[] {
},
{
name: "BTC",
signer: new SignerBtc(client, windowRef.utxoGlobal.bitcoinSigner),
signer: new SignerBtc(
client,
windowRef.utxoGlobal.bitcoinSigner,
preferredNetworks,
),
},
];
}

0 comments on commit 69c10fd

Please sign in to comment.