Skip to content

Commit

Permalink
Merge pull request #354 from enkryptcom/feature/kadena-provider
Browse files Browse the repository at this point in the history
feat: kadena provider
  • Loading branch information
kvhnuke authored May 2, 2024
2 parents 0bfd4ce + 4959d95 commit a240c91
Show file tree
Hide file tree
Showing 96 changed files with 7,618 additions and 235 deletions.
15 changes: 10 additions & 5 deletions packages/extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@
"private": true,
"scripts": {
"zip": "cd dist; zip -r release.zip *;",
"build:chrome": "cross-env BROWSER='chrome' vue-cli-service build && yarn build:rollup",
"build:operaedge": "cross-env BROWSER='opera-edge' vue-cli-service build && cross-env BROWSER='opera-edge' yarn build:rollup",
"build:firefox": "cross-env BROWSER='firefox' vue-cli-service build && yarn build:rollup && node configs/get-system-info.js",
"prebuild": "yarn kadena:prebuild",
"build:chrome": "yarn prebuild && cross-env BROWSER='chrome' vue-cli-service build && yarn build:rollup",
"build:firefox": "yarn prebuild && cross-env BROWSER='firefox' vue-cli-service build && yarn build:rollup && node configs/get-system-info.js",
"build:operaedge": "yarn prebuild && cross-env BROWSER='opera-edge' vue-cli-service build && cross-env BROWSER='opera-edge' yarn build:rollup",
"lint": "vue-cli-service lint --fix",
"build:rollup": "cross-env minify=on rollup --config configs/rollup.config.contentscript.mjs && cross-env minify=on rollup --config configs/rollup.config.inject.mjs",
"inspectWebpack": "vue-cli-service inspect > webpack.log",
"kadena:prebuild": "pactjs contract-generate --contract=coin --api https://api.chainweb.com/chainweb/0.0/mainnet01/chain/1/pact",
"test": "ts-mocha --require ./configs/testNullCompiler.js --paths -p configs/tsconfig.test.json ./**/*.mocha.ts",
"watch": "rimraf dist && concurrently 'npm:watch-*(!firefox)'",
"watch:firefox": "concurrently 'npm:watch-*(!chrome)'",
"watch": "yarn prebuild && rimraf dist && concurrently 'npm:watch-*(!firefox)'",
"watch:firefox": "yarn prebuild && concurrently 'npm:watch-*(!chrome)'",
"watch-contentscript": "rollup --watch --config configs/rollup.config.contentscript.mjs",
"watch-inject": "rollup --watch --config configs/rollup.config.inject.mjs",
"watch-vue-chrome": "cross-env BROWSER='chrome' vue-cli-service build --watch --no-clean",
Expand All @@ -32,6 +34,7 @@
"@ethereumjs/common": "^4.3.0",
"@ethereumjs/tx": "^5.3.0",
"@ethereumjs/util": "^9.0.3",
"@kadena/client": "^1.2.0",
"@ledgerhq/hw-transport-webusb": "^6.28.5",
"@metamask/eth-sig-util": "^7.0.1",
"@rollup/plugin-replace": "^5.0.5",
Expand All @@ -57,6 +60,7 @@
"memoize-one": "^6.0.0",
"moment": "^2.30.1",
"nanoevents": "^9.0.0",
"pact-lang-api": "^4.3.6",
"pinia": "^2.1.7",
"qrcode.vue": "^3.4.1",
"switch-ts": "^1.1.1",
Expand All @@ -74,6 +78,7 @@
},
"devDependencies": {
"@babel/plugin-transform-class-static-block": "^7.24.1",
"@kadena/pactjs-cli": "^1.7.0",
"@polkadot/api": "^10.12.4",
"@polkadot/extension-inject": "^0.46.9",
"@polkadot/keyring": "^12.6.2",
Expand Down
1 change: 1 addition & 0 deletions packages/extension/src/libs/background/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class BackgroundHandler {
[ProviderName.ethereum]: {},
[ProviderName.polkadot]: {},
[ProviderName.bitcoin]: {},
[ProviderName.kadena]: {},
};
this.#providers = Providers;
}
Expand Down
6 changes: 4 additions & 2 deletions packages/extension/src/libs/background/types.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import BitcoinProvider from "@/providers/bitcoin";
import type EthereumProvider from "@/providers/ethereum";
import type PolkadotProvider from "@/providers/polkadot";
import type KadenaProvider from "@/providers/kadena";

export interface TabProviderType {
[key: string]: Record<
number,
EthereumProvider | PolkadotProvider | BitcoinProvider
EthereumProvider | PolkadotProvider | BitcoinProvider | KadenaProvider
>;
}
export interface ProviderType {
[key: string]:
| typeof EthereumProvider
| typeof PolkadotProvider
| typeof BitcoinProvider;
| typeof BitcoinProvider
| typeof KadenaProvider;
}
export interface ExternalMessageOptions {
savePersistentEvents: boolean;
Expand Down
10 changes: 10 additions & 0 deletions packages/extension/src/libs/domain-state/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ class DomainState {
if (state.selectedNetwork) return state.selectedNetwork;
return null;
}
async setSelectedSubNetwork(id: string): Promise<void> {
const state = await this.getState();
state.selectedSubNetworkId = id;
await this.setState(state);
}
async getSelectedSubNetWork(): Promise<string | null> {
const state = await this.getState();
if (state.selectedSubNetworkId) return state.selectedSubNetworkId;
return null;
}
async setSelectedAddress(address: string): Promise<void> {
const state = await this.getState();
state.selectedAddress = address;
Expand Down
1 change: 1 addition & 0 deletions packages/extension/src/libs/domain-state/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ export enum StorageKeys {
}
export interface IState {
selectedNetwork?: string;
selectedSubNetworkId?: string;
selectedAddress?: string;
}
62 changes: 42 additions & 20 deletions packages/extension/src/libs/utils/initialize-wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,49 @@ import KeyRing from "@/libs/keyring/keyring";
import EthereumNetworks from "@/providers/ethereum/networks";
import PolkadotNetworks from "@/providers/polkadot/networks";
import BitcoinNetworks from "@/providers/bitcoin/networks";
import { WalletType } from "@enkryptcom/types";
export default async (mnemonic: string, password: string): Promise<void> => {
import KadenaNetworks from "@/providers/kadena/networks";
import { NetworkNames, WalletType } from "@enkryptcom/types";
import { getAccountsByNetworkName } from "@/libs/utils/accounts";
export const initAccounts = async (keyring: KeyRing) => {
const secp256k1btc = await getAccountsByNetworkName(NetworkNames.Bitcoin);
const secp256k1 = await getAccountsByNetworkName(NetworkNames.Ethereum);
const sr25519 = await getAccountsByNetworkName(NetworkNames.Polkadot);
const ed25519kda = await getAccountsByNetworkName(NetworkNames.Kadena);
if (secp256k1.length == 0)
await keyring.saveNewAccount({
basePath: EthereumNetworks.ethereum.basePath,
name: "EVM Account 1",
signerType: EthereumNetworks.ethereum.signer[0],
walletType: WalletType.mnemonic,
});
if (sr25519.length == 0)
await keyring.saveNewAccount({
basePath: PolkadotNetworks.polkadot.basePath,
name: "Substrate Account 1",
signerType: PolkadotNetworks.polkadot.signer[0],
walletType: WalletType.mnemonic,
});
if (secp256k1btc.length == 0)
await keyring.saveNewAccount({
basePath: BitcoinNetworks.bitcoin.basePath,
name: "Bitcoin Account 1",
signerType: BitcoinNetworks.bitcoin.signer[0],
walletType: WalletType.mnemonic,
});
if (ed25519kda.length == 0)
await keyring.saveNewAccount({
basePath: KadenaNetworks.kadena.basePath,
name: "Kadena Account 1",
signerType: KadenaNetworks.kadena.signer[0],
walletType: WalletType.mnemonic,
});
};
export const onboardInitializeWallets = async (
mnemonic: string,
password: string
): Promise<void> => {
const kr = new KeyRing();
await kr.init(mnemonic, password);
await kr.unlock(password);
await kr.saveNewAccount({
basePath: EthereumNetworks.ethereum.basePath,
name: "EVM Account 1",
signerType: EthereumNetworks.ethereum.signer[0],
walletType: WalletType.mnemonic,
});
await kr.saveNewAccount({
basePath: PolkadotNetworks.polkadot.basePath,
name: "Substrate Account 1",
signerType: PolkadotNetworks.polkadot.signer[0],
walletType: WalletType.mnemonic,
});
await kr.saveNewAccount({
basePath: BitcoinNetworks.bitcoin.basePath,
name: "Bitcoin Account 1",
signerType: BitcoinNetworks.bitcoin.signer[0],
walletType: WalletType.mnemonic,
});
await initAccounts(kr);
};
9 changes: 9 additions & 0 deletions packages/extension/src/libs/utils/networks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@ import { NetworkNames } from "@enkryptcom/types";
import EthereumNetworks from "@/providers/ethereum/networks";
import PolkadotNetworks from "@/providers/polkadot/networks";
import BitcoinNetworks from "@/providers/bitcoin/networks";
import KadenaNetworks from "@/providers/kadena/networks";
import { BaseNetwork } from "@/types/base-network";
import CustomNetworksState from "../custom-networks-state";
import { CustomEvmNetwork } from "@/providers/ethereum/types/custom-evm-network";
import Ethereum from "@/providers/ethereum/networks/eth";
import Polkadot from "@/providers/polkadot/networks/polkadot";
import Bitcoin from "@/providers/bitcoin/networks/bitcoin";
import Kadena from "@/providers/kadena/networks/kadena";

const providerNetworks: Record<ProviderName, Record<string, BaseNetwork>> = {
[ProviderName.ethereum]: EthereumNetworks,
[ProviderName.polkadot]: PolkadotNetworks,
[ProviderName.bitcoin]: BitcoinNetworks,
[ProviderName.kadena]: KadenaNetworks,
[ProviderName.enkrypt]: {},
};
const getAllNetworks = async (): Promise<BaseNetwork[]> => {
Expand All @@ -26,6 +29,7 @@ const getAllNetworks = async (): Promise<BaseNetwork[]> => {
return (Object.values(EthereumNetworks) as BaseNetwork[])
.concat(Object.values(PolkadotNetworks) as BaseNetwork[])
.concat(Object.values(BitcoinNetworks) as BaseNetwork[])
.concat(Object.values(KadenaNetworks) as BaseNetwork[])
.concat(customNetworks);
};
const getNetworkByName = async (
Expand Down Expand Up @@ -53,10 +57,12 @@ const getProviderNetworkByName = async (
const DEFAULT_EVM_NETWORK_NAME = NetworkNames.Ethereum;
const DEFAULT_SUBSTRATE_NETWORK_NAME = NetworkNames.Polkadot;
const DEFAULT_BTC_NETWORK_NAME = NetworkNames.Bitcoin;
const DEFAULT_KADENA_NETWORK_NAME = NetworkNames.Kadena;

const DEFAULT_EVM_NETWORK = Ethereum;
const DEFAULT_SUBSTRATE_NETWORK = Polkadot;
const DEFAULT_BTC_NETWORK = Bitcoin;
const DEFAULT_KADENA_NETWORK = Kadena;

const POPULAR_NAMES = [
NetworkNames.Bitcoin,
Expand All @@ -66,6 +72,7 @@ const POPULAR_NAMES = [
NetworkNames.Binance,
NetworkNames.Rootstock,
NetworkNames.Optimism,
NetworkNames.Kadena,
];
export {
getAllNetworks,
Expand All @@ -78,4 +85,6 @@ export {
DEFAULT_EVM_NETWORK,
DEFAULT_SUBSTRATE_NETWORK,
DEFAULT_BTC_NETWORK,
DEFAULT_KADENA_NETWORK,
DEFAULT_KADENA_NETWORK_NAME,
};
2 changes: 2 additions & 0 deletions packages/extension/src/providers/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import EthereumProvider from "@/providers/ethereum";
import PolkadotProvider from "@/providers/polkadot";
import BitcoinProvider from "@/providers/bitcoin";
import KadenaProvider from "@/providers/kadena";
import { ProviderName } from "@/types/provider";

export default {
[ProviderName.ethereum]: EthereumProvider,
[ProviderName.polkadot]: PolkadotProvider,
[ProviderName.bitcoin]: BitcoinProvider,
[ProviderName.kadena]: KadenaProvider,
};
83 changes: 83 additions & 0 deletions packages/extension/src/providers/kadena/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import getRequestProvider, { RequestClass } from "@enkryptcom/request";
import { MiddlewareFunction, OnMessageResponse } from "@enkryptcom/types";
import Middlewares from "./methods";
import EventEmitter from "eventemitter3";
import {
BackgroundProviderInterface,
ProviderName,
ProviderRPCRequest,
} from "@/types/provider";
import GetUIPath from "@/libs/utils/get-ui-path";
import PublicKeyRing from "@/libs/keyring/public-keyring";
import UIRoutes from "./ui/routes/names";

import Networks from "./networks";
import { BaseNetwork } from "@/types/base-network";
import { KadenaNetwork } from "./types/kadena-network";

class KadenaProvider
extends EventEmitter
implements BackgroundProviderInterface
{
network: KadenaNetwork;
requestProvider: RequestClass;
middlewares: MiddlewareFunction[] = [];
namespace: string;
KeyRing: PublicKeyRing;
UIRoutes = UIRoutes;
toWindow: (message: string) => void;

constructor(
toWindow: (message: string) => void,
network: KadenaNetwork = Networks.kadena
) {
super();
this.network = network;
this.toWindow = toWindow;
this.setMiddleWares();
this.requestProvider = getRequestProvider("", this.middlewares);
this.requestProvider.on("notification", (notif: any) => {
this.sendNotification(JSON.stringify(notif));
});
this.namespace = ProviderName.kadena;
this.KeyRing = new PublicKeyRing();
}

private setMiddleWares(): void {
this.middlewares = Middlewares.map((mw) => mw.bind(this));
}

setRequestProvider(network: BaseNetwork): void {
this.network = network as KadenaNetwork;
this.requestProvider.changeNetwork(network.node);
}

request(request: ProviderRPCRequest): Promise<OnMessageResponse> {
return this.requestProvider
.request(request)
.then((res: any) => {
return {
result: JSON.stringify(res),
};
})
.catch((e: { message: any }) => {
return {
error: JSON.stringify(e.message),
};
});
}

async sendNotification(notif: string): Promise<void> {
return this.toWindow(notif);
}

async isPersistentEvent(): Promise<boolean> {
return false;
}

getUIPath(page: string): string {
return GetUIPath(page, this.namespace);
}
}

export default KadenaProvider;
57 changes: 57 additions & 0 deletions packages/extension/src/providers/kadena/inject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import EventEmitter from "eventemitter3";
import { handleIncomingMessage } from "./libs/message-handler";
import { EthereumRequest, EthereumResponse } from "@/providers/ethereum/types";
import {
ProviderName,
ProviderOptions,
ProviderType,
ProviderInterface,
SendMessageHandler,
} from "@/types/provider";
import { EnkryptWindow } from "@/types/globals";
import { KadenaNetworks } from "./types";

export class Provider extends EventEmitter implements ProviderInterface {
connected: boolean;
name: ProviderName;
type: ProviderType;
version = __VERSION__;
autoRefreshOnNetworkChange = false;
networks: typeof KadenaNetworks;
sendMessageHandler: SendMessageHandler;

constructor(options: ProviderOptions) {
super();
this.connected = true;
this.name = options.name;
this.type = options.type;
this.networks = KadenaNetworks;
this.sendMessageHandler = options.sendMessageHandler;
}

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

isConnected(): boolean {
return this.connected;
}

handleMessage(msg: string): void {
handleIncomingMessage(this, msg);
}
}

const injectDocument = (
document: EnkryptWindow | Window,
options: ProviderOptions
): void => {
const provider = new Provider(options);
document["enkrypt"]["providers"][options.name] = provider;
};

export default injectDocument;
Loading

1 comment on commit a240c91

@github-actions
Copy link

Choose a reason for hiding this comment

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

Please sign in to comment.