Skip to content

Commit

Permalink
devop: solana wallet-standard connection
Browse files Browse the repository at this point in the history
  • Loading branch information
kvhnuke committed Aug 13, 2024
1 parent e418920 commit c143051
Show file tree
Hide file tree
Showing 30 changed files with 1,598 additions and 361 deletions.
6 changes: 5 additions & 1 deletion packages/extension/configs/rollup.config.base.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import nodeResolve from "@rollup/plugin-node-resolve";
import { uglify } from "rollup-plugin-uglify";
import inject from "@rollup/plugin-inject";
import replace from "@rollup/plugin-replace";
import json from "@rollup/plugin-json";
import packageJson from "../package.json" assert { type: "json" };

const enableMinification = process.env.minify === "on";
Expand All @@ -20,8 +21,11 @@ const base = {
__VERSION__: JSON.stringify(packageJson.version),
__IS_OPERA__: process.env.BROWSER === "opera-edge",
}),
typescript(),
typescript({
exclude: [/node_modules/],
}),
commonjs(),
json(),
inject({
Buffer: ["buffer", "Buffer"],
}),
Expand Down
3 changes: 3 additions & 0 deletions packages/extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,15 @@
"@rollup/plugin-replace": "^5.0.7",
"@solana-developers/helpers": "^2.4.0",
"@solana/spl-token": "^0.4.8",
"@solana/wallet-standard-features": "^1.2.0",
"@solana/web3.js": "^1.95.2",
"@types/chrome": "^0.0.269",
"@types/events": "^3.0.3",
"@types/less": "^3.0.6",
"@types/lodash": "^4.17.7",
"@types/utf-8-validate": "^5.0.2",
"@vueuse/core": "^10.11.0",
"@wallet-standard/base": "^0.0.0-20240703212708",
"add": "^2.0.6",
"bignumber.js": "^9.1.2",
"bip39": "^3.1.0",
Expand Down Expand Up @@ -97,6 +99,7 @@
"@polkadot/wasm-crypto": "^7.3.2",
"@rollup/plugin-commonjs": "^26.0.1",
"@rollup/plugin-inject": "^5.0.5",
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-typescript": "^11.1.6",
"@types/bs58": "^4.0.4",
Expand Down
2 changes: 1 addition & 1 deletion packages/extension/src/providers/solana/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class SolanaProvider
this.requestProvider.on("notification", (notif: any) => {
this.sendNotification(JSON.stringify(notif));
});
this.namespace = ProviderName.bitcoin;
this.namespace = ProviderName.solana;
this.KeyRing = new PublicKeyRing();
}
private setMiddleWares(): void {
Expand Down
175 changes: 81 additions & 94 deletions packages/extension/src/providers/solana/inject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,113 +9,107 @@ import {
SendMessageHandler,
} from "@/types/provider";
import { EnkryptWindow } from "@/types/globals";
import { SolanaNetwork } from "./types/sol-network";
import { InternalMethods } from "@/types/messenger";
import { SettingsType } from "@/libs/settings-state/types";

export class Provider extends EventEmitter implements ProviderInterface {
import { Enkrypt, EnkryptSolAccount } from "./libs/wallet-standard/window";
import type {
PublicKey,
SendOptions,
Transaction,
VersionedTransaction,
} from "@solana/web3.js";
import type {
SolanaSignInInput,
SolanaSignInOutput,
} from "@solana/wallet-standard-features";
import { initialize } from "./libs/wallet-standard";
import { EnkryptWalletAccount } from "./libs/wallet-standard/account";
import { SolSignInResponse, SolSignTransactionRequest } from "./ui/types";

export class Provider
extends EventEmitter
implements ProviderInterface, Enkrypt
{
connected: boolean;
name: ProviderName;
type: ProviderType;
version: string = __VERSION__;
autoRefreshOnNetworkChange = false;
networks: typeof SolanaNetwork;
sendMessageHandler: SendMessageHandler;
accounts: EnkryptSolAccount[];
constructor(options: ProviderOptions) {
super();
this.connected = true;
this.name = options.name;
this.type = options.type;
this.networks = SolanaNetwork;
this.sendMessageHandler = options.sendMessageHandler;
this.accounts = [];
}

async request(request: EthereumRequest): Promise<EthereumResponse> {
const res = (await this.sendMessageHandler(
this.name,
JSON.stringify(request)
)) as EthereumResponse;
return res;
}

requestAccounts = async () => {
return this.request({
method: "btc_requestAccounts",
});
};

getAccounts = async () => {
return this.request({
method: "btc_requestAccounts",
});
};

getPublicKey = async () => {
connect(
options?: { onlyIfTrusted?: boolean | undefined } | undefined
): Promise<EnkryptSolAccount[]> {
return this.request({
method: "btc_getPublicKey",
method: "sol_connect",
params: [options],
}).then((res: { address: string; pubkey: string }[]) => {
this.accounts = res;
return res;
});
};

getNetwork = async () => {
return this.request({
method: "btc_getNetwork",
});
};

switchNetwork = async (network: string) => {
return this.request({
method: "btc_switchNetwork",
params: [network],
});
};

getBalance = async () => {
}
disconnect(): Promise<void> {
console.log("disconnect");
return Promise.reject("not implemented");
}
signAndSendTransaction<T extends Transaction | VersionedTransaction>(
transaction: T,
options?: SendOptions | undefined
): Promise<{ signature: string }> {
console.log("signAndSendTransaction");
return Promise.reject("not implemented");
}
signAllTransactions<T extends Transaction | VersionedTransaction>(
transactions: T[]
): Promise<T[]> {
console.log("signAllTransactions");
return Promise.reject("not implemented");
}
signIn(input?: SolanaSignInInput | undefined): Promise<SolSignInResponse> {
return this.request({
method: "btc_getBalance",
method: "sol_signInMessage",
params: [JSON.stringify(input)],
}).then((res: SolSignInResponse) => {
const accExists = this.accounts.find(
(acc) => acc.address === res.address
);
if (!accExists) {
this.accounts.push({ address: res.address, pubkey: res.pubkey });
}
return res;
});
};

signPsbt = async (psbtHex: string, options?: any) => {
}
signMessage(options: {
address: string;
message: string;
}): Promise<SolSignInResponse> {
return this.request({
method: "btc_signPsbt",
params: [psbtHex, options],
});
};

signMessage = async (text: string, type: string) => {
method: "sol_signMessage",
params: [JSON.stringify(options)],
}).then((res: SolSignInResponse) => res);
}
signTransaction(transaction: SolSignTransactionRequest): Promise<string> {
console.log("signTransaction");
return this.request({
method: "btc_signMessage",
params: [text, type],
});
};

getInscriptions = async () => {
return Promise.reject("not implemented");
};

sendBitcoin = async () => {
return Promise.reject("not implemented");
};

sendInscription = async () => {
return Promise.reject("not implemented");
};

inscribeTransfer = async () => {
return Promise.reject("not implemented");
};

pushTx = async () => {
return Promise.reject("not implemented");
};

signPsbts = async () => {
return Promise.reject("not implemented");
};

pushPsbt = async () => {
return Promise.reject("not implemented");
};
method: "sol_signTransaction",
params: [JSON.stringify(transaction)],
}).then((res: string) => res);
}
async request(request: EthereumRequest): Promise<any> {
const res = (await this.sendMessageHandler(
this.name,
JSON.stringify(request)
)) as EthereumResponse;
return res;
}

isConnected(): boolean {
return this.connected;
Expand All @@ -130,14 +124,7 @@ const injectDocument = (
options: ProviderOptions
): void => {
const provider = new Provider(options);
options
.sendMessageHandler(
ProviderName.enkrypt,
JSON.stringify({ method: InternalMethods.getSettings, params: [] })
)
.then((settings: SettingsType) => {
if (settings.btc.injectUnisat) document["unisat"] = provider;
});
initialize(provider);
document["enkrypt"]["providers"][options.name] = provider;
};
export default injectDocument;
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// This is copied with modification from @wallet-standard/wallet

import {
SolanaSignAndSendTransaction,
SolanaSignMessage,
SolanaSignTransaction,
} from "@solana/wallet-standard-features";
import type { WalletAccount } from "@wallet-standard/base";
import { SOLANA_CHAINS } from "./solana";

const chains = SOLANA_CHAINS;
const features = [
SolanaSignAndSendTransaction,
SolanaSignTransaction,
SolanaSignMessage,
] as const;

export class EnkryptWalletAccount implements WalletAccount {
readonly #address: WalletAccount["address"];
readonly #publicKey: WalletAccount["publicKey"];
readonly #chains: WalletAccount["chains"];
readonly #features: WalletAccount["features"];
readonly #label: WalletAccount["label"];
readonly #icon: WalletAccount["icon"];

get address() {
return this.#address;
}

get publicKey() {
return this.#publicKey.slice();
}

get chains() {
return this.#chains.slice();
}

get features() {
return this.#features.slice();
}

get label() {
return this.#label;
}

get icon() {
return this.#icon;
}

constructor({
address,
publicKey,
label,
icon,
}: Omit<WalletAccount, "chains" | "features">) {
if (new.target === EnkryptWalletAccount) {
Object.freeze(this);
}

this.#address = address;
this.#publicKey = publicKey;
this.#chains = chains;
this.#features = features;
this.#label = label;
this.#icon = icon;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import type { WalletIcon } from "@wallet-standard/base";
export const icon: WalletIcon =
"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODEiIGhlaWdodD0iODEiIHZpZXdCb3g9IjAgMCA4MSA4MSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xNy4wMDU3IDE3LjAwNjJDMTguOTMwMyAxNS4wODE2IDIxLjU0MDUgMTQuMDAwNCAyNC4yNjIyIDE0LjAwMDRMNjcuMzI5NiAxNFYyMS44NzQxQzY3LjMyOTYgMjMuODMwNSA2Ni41NTIzIDI1LjcwNjcgNjUuMTY5IDI3LjA5QzYzLjc4NTcgMjguNDczMyA2MS45MDk1IDI5LjI1MDQgNTkuOTUzMiAyOS4yNTA0SDM5LjcwNDVDMzYuOTgyOCAyOS4yNTA0IDM0LjM3MjYgMzAuMzMxNiAzMi40NDggMzIuMjU2MUMzMC41MjM1IDM0LjE4MDcgMjkuNDQyMyAzNi43OTA5IDI5LjQ0MjMgMzkuNTEyNlY0Mi4xMjQyQzI5LjQ0MjMgNDQuODQ1OSAzMC41MjM1IDQ3LjQ1NjEgMzIuNDQ4IDQ5LjM4MDZDMzQuMzcyNiA1MS4zMDUxIDM2Ljk4MjggNTIuMzg2MyAzOS43MDQ1IDUyLjM4NjNINTkuOTUzMkM2MS45MDk1IDUyLjM4NjMgNjMuNzg1NyA1My4xNjM1IDY1LjE2OSA1NC41NDY4QzY2LjU1MjMgNTUuOTMwMSA2Ny4zMjk2IDU3LjgwNjMgNjcuMzI5NiA1OS43NjI2VjY3LjMzSDI0LjI2MjJDMjEuNTQwNSA2Ny4zMyAxOC45MzAzIDY2LjI0ODggMTcuMDA1NyA2NC4zMjQzQzE1LjA4MTIgNjIuMzk5NyAxNCA1OS43ODk1IDE0IDU3LjA2NzhWMjQuMjYyNkMxNCAyMS41NDA5IDE1LjA4MTIgMTguOTMwNyAxNy4wMDU3IDE3LjAwNjJaTTQwLjE0NzkgMzMuNTQyM0g2MC45MTU3QzY0LjQ1OCAzMy41NDIzIDY3LjMyOTUgMzYuNDEzOCA2Ny4zMjk1IDM5Ljk1NjFWNDEuNjgxNkM2Ny4zMjk1IDQ1LjIyMzggNjQuNDU4IDQ4LjA5NTQgNjAuOTE1NyA0OC4wOTU0SDQwLjE0NzlDMzYuNjA1NyA0OC4wOTU0IDMzLjczNDEgNDUuMjIzOCAzMy43MzQxIDQxLjY4MTZWMzkuOTU2MUMzMy43MzQxIDM2LjQxMzggMzYuNjA1NyAzMy41NDIzIDQwLjE0NzkgMzMuNTQyM1oiIGZpbGw9InVybCgjcGFpbnQwX2xpbmVhcl8yODdfMjM1OSkiLz4KPGRlZnM+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQwX2xpbmVhcl8yODdfMjM1OSIgeDE9IjE5LjM2MDIiIHkxPSIxNCIgeDI9IjU2Ljc2OTYiIHkyPSI2OS44MDA1IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CjxzdG9wIHN0b3AtY29sb3I9IiNDNTQ5RkYiLz4KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjNjU0QkZGIi8+CjwvbGluZWFyR3JhZGllbnQ+CjwvZGVmcz4KPC9zdmc+Cg==";
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./initialize";
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { registerWallet } from "./register";
import { EnkryptWallet } from "./wallet";
import type { Enkrypt } from "./window";

export function initialize(enkrypt: Enkrypt): void {
console.log(new EnkryptWallet(enkrypt));
registerWallet(new EnkryptWallet(enkrypt));
}
Loading

0 comments on commit c143051

Please sign in to comment.