Skip to content

Commit

Permalink
New Solana Provider using secure-background/client for web & xnfts (#…
Browse files Browse the repository at this point in the history
…4213)

* add madlads.com to wl

* restructure secure-background

* Fully typed Client-Server requests

* setup secure background channels

* End to end working message signing through new client and secure-background channel

* Working Content->background->UI->background->Content message passing

* Split secure-background & secure-client

* secure-background/clients exports

* Clarify Transport From/To naming + correctly close Popup after opening it.

* Add ExtensionTransports and solidify Error handling

* UnlockKeyring event + new extension message passing

* Combine SecureUI and SecureBackground events + add transports to recoil

* fix build:fresh

* Add secure-client to dockerfiles

* Add request.origin

* Add tamagui to secure-client & fix circular dependencies

* fix devmode transport issues

* Working confirmation prompt

* Create RequestResponder

* e2e solana signMessage w/o unlock & approve origin

* SecureStore refactor

* Remove secure-client import from solana provider for merge

this makes the merge a refactor only without anything using the new secure-background service yet.

* Lock down deprecated and private methods in SecureStore

pass them to migrations specifically via MigrationPrivateStoreInterface

* Clean up KeyringStoreState enum and move it to secure-background/types

* Lock down deprecated and private methods in SecureStore

pass them to migrations specifically via MigrationPrivateStoreInterface

* Clean up KeyringStoreState enum and move it to secure-background/types

* Fetch user data from secureUI

* move origin from clients to transport.

* Setup SecureUI request subscription & queue

* Fix import issue.

* cleanup

* animation improvement

* Sign Message request with forced unlock

* Solana provider connect

incl
- background internal events
- background triggered login prompts

* Approve Origin Request

* Add solana disconnect

* solana send & sendAndConfirm transaction

* Fix xnft connection -> use "enhanced" background connection

* Emit keyring unlocked event

* Use default Connection for backend/solana-connect and properly reset onUnlock

* Solana SignAllTransactions

* new NotificationsClient

* Cleanup and logging

* separate extension & secureUI origins

* Cleanup + disable new provider

* remove console.log
  • Loading branch information
ph101pp authored Jun 23, 2023
1 parent 69e841f commit f566c06
Show file tree
Hide file tree
Showing 59 changed files with 2,646 additions and 476 deletions.
2 changes: 1 addition & 1 deletion examples/clients/simple/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"wagmi": "^0.6.3"
},
"devDependencies": {
"@parcel/transformer-html": "^2.9.1",
"@parcel/transformer-html": "^2.9.2",
"@parcel/transformer-posthtml": "^2.9.1",
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
Expand Down
2 changes: 1 addition & 1 deletion examples/clients/simple/src/solana/SendAllButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export const SendAllButton: FC = () => {
transaction2.feePayer = wallet.publicKey;
transaction3.feePayer = wallet.publicKey;

const signedTxs = await wallet.signAllTransactions([
const signedTxs = await wallet.signAllTransactions!([
transaction1,
transaction2,
transaction3,
Expand Down
17 changes: 7 additions & 10 deletions examples/xnft/prices/src/App/_helpers/redux.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import type { Dispatch, MutableRefObject, ReactNode } from "react";
import React, {
useMemo,
useEffect,
useContext,
useState,
createContext,
useCallback,
Dispatch,
useRef,
MutableRefObject,
useContext,
useEffect,
useMemo,
useReducer,
ReactNode,
createContext,
useRef,
useState,
} from "react";

export type Reducer<State, Actions> = (state: State, action: Actions) => State;
Expand Down Expand Up @@ -101,7 +99,6 @@ function useThunk<State, Actions>([state, dispatch]: [
const containerRef: MutableRefObject<State> = useRef<State>(state);
const thunkDispatch: ThunkDispatch<State, Actions> = useCallback(
(action: Actions | Thunk<State, Actions>) => {
// console.log("PCA", "useThunk", action);
switch (typeof action) {
case "object": {
dispatch(action as Actions);
Expand Down
2 changes: 1 addition & 1 deletion packages/app-extension/src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { ErrorBoundary } from "./ErrorBoundary";

const Router = lazy(() => import("./Router"));

import type { TransportSender } from "@coral-xyz/secure-client";
import type { TransportSender } from "@coral-xyz/secure-client/types";

import "@fontsource/inter/500.css";
import "@fontsource/inter/600.css";
Expand Down
34 changes: 26 additions & 8 deletions packages/app-extension/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import {
isValidEventOrigin,
openPopupWindow,
} from "@coral-xyz/common";
import type { SECURE_EVENTS } from "@coral-xyz/secure-client";
import {
FromExtensionTransportSender,
ToSecureUITransportReceiver,
} from "@coral-xyz/secure-client";
import type { SECURE_EVENTS } from "@coral-xyz/secure-client/types";
import { SecureUI } from "@coral-xyz/secure-client/ui";
import { v4 } from "uuid";

Expand All @@ -32,18 +32,34 @@ chrome.runtime
})
.catch(console.error);

const urlParams = new URLSearchParams(window.location.search);
const requestWindowId = urlParams.get("windowId");
// if popup was passed windowId it was opened by secure-background
// and should not render app since secure-ui will handle the request.
const shouldRenderApp = !requestWindowId;
const windowId = requestWindowId ?? v4();

// Send connect event to background script to open channel.
// add unique name so background can identify the popup.
const urlParams = new URLSearchParams(window.location.search);
const windowId = urlParams.get("windowId") ?? v4();
const port = chrome.runtime.connect({ name: windowId });

const secureUITransportReceiver = new ToSecureUITransportReceiver<
SECURE_EVENTS,
"confirmation"
>(port);
const extensionTransportSender =
new FromExtensionTransportSender<SECURE_EVENTS>();
new FromExtensionTransportSender<SECURE_EVENTS>({
name: "Backpack Extension",
address: window.location.origin,
context: "extension",
});
const secureUITransportSender = new FromExtensionTransportSender<SECURE_EVENTS>(
{
name: "Backpack Extension",
address: window.location.origin,
context: "secureUI",
}
);
//
// Configure event listeners.
//
Expand All @@ -69,12 +85,14 @@ const container = document.getElementById("root");
const root = createRoot(container!);
root.render(
<>
<Suspense fallback={null}>
<App secureBackgroundSender={extensionTransportSender} />
</Suspense>
{shouldRenderApp ? (
<Suspense fallback={null}>
<App secureBackgroundSender={extensionTransportSender} />
</Suspense>
) : null}
<Suspense fallback={null}>
<SecureUI
secureBackgroundSender={extensionTransportSender}
secureBackgroundSender={secureUITransportSender}
secureUIReceiver={secureUITransportReceiver}
/>
</Suspense>
Expand Down
1 change: 1 addition & 0 deletions packages/background/src/backend/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ export class Backend {
const signature = await this.solanaSignTransaction(txStr, walletAddress);
const pubkey = new PublicKey(walletAddress);
const tx = deserializeTransaction(txStr);

tx.addSignature(pubkey, Buffer.from(bs58.decode(signature)));

// Send it to the network.
Expand Down
7 changes: 6 additions & 1 deletion packages/background/src/backend/solana-connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
Blockchain,
confirmTransaction,
customSplTokenAccounts,
DEFAULT_SOLANA_CLUSTER,
fetchSplMetadataUri,
getLogger,
NOTIFICATION_BLOCKCHAIN_KEYRING_CREATED,
Expand Down Expand Up @@ -110,9 +111,12 @@ export function start(events: EventEmitter): SolanaConnectionBackend {
return b;
}

const defaultSolanaUrl =
process.env.DEFAULT_SOLANA_CONNECTION_URL || DEFAULT_SOLANA_CLUSTER;

export class SolanaConnectionBackend {
private cache = new Map<string, CachedValue<any>>();
private connection?: Connection;
private connection?: Connection = new Connection(defaultSolanaUrl);
private url?: string;
private pollIntervals: Array<any>;
private events: EventEmitter;
Expand Down Expand Up @@ -184,6 +188,7 @@ export class SolanaConnectionBackend {
};

const handleKeyringStoreLocked = (_notif: Notification) => {
this.connection = new Connection(defaultSolanaUrl);
this.stopPolling();
};

Expand Down
15 changes: 10 additions & 5 deletions packages/background/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import {
KeyringStore,
secureStore,
} from "@coral-xyz/secure-background/legacyExport";
import { startSecureService } from "@coral-xyz/secure-background/service";
import type { SECURE_EVENTS } from "@coral-xyz/secure-client";
import {
BackendNotificationBroadcaster,
combineTransportReceivers,
FromContentScriptTransportReceiver,
FromExtensionTransportReceiver,
mockTransportSender,
ToSecureUITransportSender,
} from "@coral-xyz/secure-client";
import { startSecureService } from "@coral-xyz/secure-client/service";
import type { SECURE_EVENTS } from "@coral-xyz/secure-client/types";
import { EventEmitter } from "eventemitter3";

import * as coreBackend from "./backend/core";
Expand Down Expand Up @@ -45,17 +45,22 @@ export function start(cfg: Config): Background {
const _ethereumConnection = ethereumConnection.start(cfg, events, ethereumB);

if (!cfg.isMobile) {
const notificationBroadcaster = new BackendNotificationBroadcaster(events);
const contentScriptReceiver = new FromContentScriptTransportReceiver();
const extensionReceiver = new FromExtensionTransportReceiver();
const secureUISender = new ToSecureUITransportSender<
SECURE_EVENTS,
"confirmation"
>();
>({
address: "secure-background",
name: "Backpack",
context: "background",
});

// New secure service
startSecureService(
{
backendNotificationClient: mockTransportSender,
notificationBroadcaster,
secureUIClient: secureUISender,
secureServer: combineTransportReceivers(
contentScriptReceiver,
Expand Down
4 changes: 1 addition & 3 deletions packages/data-components/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist/esm/",
"rootDir": "./src",
"noUnusedLocals": true,
"noUnusedParameters": true
"rootDir": "./src"
}
}
1 change: 0 additions & 1 deletion packages/provider-core/src/common/solana.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import type {
SimulatedTransactionResponse,
Transaction,
TransactionSignature,
Version,
VersionedTransaction,
} from "@solana/web3.js";
import { decode, encode } from "bs58";
Expand Down
Loading

1 comment on commit f566c06

@vercel
Copy link

@vercel vercel bot commented on f566c06 Jun 23, 2023

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.