Skip to content

Commit

Permalink
wip 2
Browse files Browse the repository at this point in the history
  • Loading branch information
macalinao committed Mar 24, 2024
1 parent c96d01c commit 95b5b7c
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 37 deletions.
44 changes: 36 additions & 8 deletions packages/solana-contrib/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,56 @@ import type {
Signer,
SimulatedTransactionResponse,
Transaction,
TransactionVersion,
} from "@solana/web3.js";
import { VersionedTransaction } from "@solana/web3.js";

import type { BroadcastOptions, PendingTransaction } from "./index.js";

/**
* Wallet interface for objects that can be used to sign provider transactions.
*
* This interface comes from Anchor.
*/
export interface Wallet {
export type SupportedTransactionVersions = Set<TransactionVersion> | null;

export const isVersionedTransaction = (
tx: Transaction | VersionedTransaction,
): tx is VersionedTransaction => {
return "version" in tx || tx instanceof VersionedTransaction;
};

export const ALL_TRANSACTION_VERSIONS: Set<TransactionVersion> =
new Set<TransactionVersion>(["legacy", 0]);

export type TransactionOrVersionedTransaction<
S extends SupportedTransactionVersions,
> = S extends null ? Transaction : Transaction | VersionedTransaction;

export interface MultiVersionWalletAdapter<
V extends SupportedTransactionVersions,
> {
readonly supportedTransactionVersions: V;
/**
* Signs a transaction with the wallet.
* @param tx
*/
signTransaction(tx: Transaction): Promise<Transaction>;
signTransaction<T extends TransactionOrVersionedTransaction<V>>(
tx: T,
): Promise<T>;

/**
* Signs all transactions with the wallet.
* @param txs
*/
signAllTransactions(txs: Transaction[]): Promise<Transaction[]>;
signAllTransactions<T extends TransactionOrVersionedTransaction<V>>(
txs: T[],
): Promise<T[]>;
}

/**
* Wallet interface for objects that can be used to sign provider transactions.
*
* This interface comes from Anchor.
*/
export interface Wallet<
V extends SupportedTransactionVersions = SupportedTransactionVersions,
> extends MultiVersionWalletAdapter<V> {
/**
* The PublicKey of the wallet.
*/
Expand Down
2 changes: 2 additions & 0 deletions packages/solana-contrib/src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { default as invariant } from "tiny-invariant";
import { SingleConnectionBroadcaster } from "./broadcaster/index.js";
import type { Broadcaster, ReadonlyProvider } from "./index.js";
import {
ALL_TRANSACTION_VERSIONS,
PendingTransaction,
SignerWallet,
TieredBroadcaster,
Expand Down Expand Up @@ -57,6 +58,7 @@ export class SolanaReadonlyProvider implements ReadonlyProvider {
}

wallet: Wallet = {
supportedTransactionVersions: ALL_TRANSACTION_VERSIONS,
signTransaction: Promise.resolve.bind(Promise),
signAllTransactions: Promise.resolve.bind(Promise),
publicKey: DEFAULT_READONLY_PUBLIC_KEY,
Expand Down
36 changes: 28 additions & 8 deletions packages/solana-contrib/src/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,53 @@ import type {
Connection,
PublicKey,
Signer,
Transaction,
} from "@solana/web3.js";

import type { Provider, Wallet } from "./interfaces.js";
import {
ALL_TRANSACTION_VERSIONS,
isVersionedTransaction,
type Provider,
type SupportedTransactionVersions,
type TransactionOrVersionedTransaction,
type Wallet,
} from "./interfaces.js";
import { SolanaProvider } from "./provider.js";

/**
* Wallet based on a Signer.
*/
export class SignerWallet implements Wallet {
export class SignerWallet implements Wallet<SupportedTransactionVersions> {
constructor(readonly signer: Signer) {}

get publicKey(): PublicKey {
return this.signer.publicKey;
}

signAllTransactions(transactions: Transaction[]): Promise<Transaction[]> {
readonly supportedTransactionVersions = ALL_TRANSACTION_VERSIONS;

signAllTransactions<
T extends TransactionOrVersionedTransaction<SupportedTransactionVersions>,
>(txs: T[]): Promise<T[]> {
return Promise.resolve(
transactions.map((tx) => {
tx.partialSign(this.signer);
txs.map((tx) => {
if (isVersionedTransaction(tx)) {
tx.sign([this.signer]);
} else {
tx.partialSign(this.signer);
}
return tx;
}),
);
}

signTransaction(transaction: Transaction): Promise<Transaction> {
transaction.partialSign(this.signer);
signTransaction<
T extends TransactionOrVersionedTransaction<SupportedTransactionVersions>,
>(transaction: T): Promise<T> {
if (isVersionedTransaction(transaction)) {
transaction.sign([this.signer]);
} else {
transaction.partialSign(this.signer);
}
return Promise.resolve(transaction);
}

Expand Down
31 changes: 19 additions & 12 deletions packages/use-solana/src/adapters/solana.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type {
Broadcaster,
MultiVersionWalletAdapter,
SignAndBroadcastOptions,
} from "@saberhq/solana-contrib";
import {
Expand All @@ -9,6 +10,8 @@ import {
import type {
EventEmitter,
SignerWalletAdapter,
SupportedTransactionVersions,
TransactionOrVersionedTransaction,
WalletAdapterEvents,
} from "@solana/wallet-adapter-base";
import { BaseSignerWalletAdapter } from "@solana/wallet-adapter-base";
Expand All @@ -18,7 +21,11 @@ import type { Connection, PublicKey, Transaction } from "@solana/web3.js";

import type { ConnectedWallet, WalletAdapter } from "./types";

export class SolanaWalletAdapter implements WalletAdapter {
export class SolanaWalletAdapter<V extends SupportedTransactionVersions>
implements WalletAdapter<boolean, V>
{
readonly supportedTransactionVersions: V;

constructor(
readonly adapter: Omit<
SignerWalletAdapter,
Expand All @@ -27,13 +34,11 @@ export class SolanaWalletAdapter implements WalletAdapter {
| "signTransaction"
| "signAllTransactions"
> &
EventEmitter<WalletAdapterEvents> & {
signTransaction: (transaction: Transaction) => Promise<Transaction>;
signAllTransactions: (
transactions: Transaction[],
) => Promise<Transaction[]>;
},
) {}
EventEmitter<WalletAdapterEvents> &
MultiVersionWalletAdapter<V>,
) {
this.supportedTransactionVersions = adapter.supportedTransactionVersions;
}

async signAndBroadcastTransaction(
transaction: Transaction,
Expand Down Expand Up @@ -116,17 +121,19 @@ export class SolanaWalletAdapter implements WalletAdapter {
return false;
}

async signAllTransactions(
transactions: Transaction[],
): Promise<Transaction[]> {
async signAllTransactions<T extends TransactionOrVersionedTransaction<V>>(
transactions: T[],
): Promise<T[]> {
return this.adapter.signAllTransactions(transactions);
}

get publicKey(): PublicKey | null {
return this.adapter.publicKey;
}

async signTransaction(transaction: Transaction): Promise<Transaction> {
async signTransaction<T extends TransactionOrVersionedTransaction<V>>(
transaction: T,
): Promise<T> {
if (!this.adapter) {
return transaction;
}
Expand Down
32 changes: 24 additions & 8 deletions packages/use-solana/src/adapters/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,21 @@ import type {
Wallet,
} from "@saberhq/solana-contrib";
import { PublicKey } from "@saberhq/solana-contrib";
import type {
SupportedTransactionVersions,
TransactionOrVersionedTransaction,
} from "@solana/wallet-adapter-base";
import type { WalletConnectWalletAdapterConfig } from "@solana/wallet-adapter-walletconnect";
import type {
Connection,
PublicKey as SolanaPublicKey,
Transaction,
} from "@solana/web3.js";

export interface WalletAdapter<Connected extends boolean = boolean>
extends Omit<Wallet, "publicKey"> {
export interface WalletAdapter<
Connected extends boolean = boolean,
V extends SupportedTransactionVersions = SupportedTransactionVersions,
> extends Omit<Wallet<V>, "publicKey"> {
publicKey: Connected extends true ? SolanaPublicKey : null;
autoApprove: boolean;
connected: Connected;
Expand Down Expand Up @@ -50,10 +56,16 @@ export type WalletAdapterBuilder = (
/**
* Wallet adapter wrapper with caching of the PublicKey built-in.
*/
export class WrappedWalletAdapter<Connected extends boolean = boolean>
implements Omit<WalletAdapter<Connected>, "publicKey">
export class WrappedWalletAdapter<
Connected extends boolean = boolean,
V extends SupportedTransactionVersions = SupportedTransactionVersions,
> implements Omit<WalletAdapter<Connected, V>, "publicKey">
{
constructor(readonly adapter: WalletAdapter<Connected>) {}
readonly supportedTransactionVersions: V;

constructor(readonly adapter: WalletAdapter<Connected, V>) {
this.supportedTransactionVersions = adapter.supportedTransactionVersions;
}

private _prevPubkey: SolanaPublicKey | null = null;
private _publicKeyCached: PublicKey | null = null;
Expand Down Expand Up @@ -103,11 +115,15 @@ export class WrappedWalletAdapter<Connected extends boolean = boolean>
);
}

signTransaction(transaction: Transaction): Promise<Transaction> {
return this.adapter.signTransaction(transaction);
signTransaction<T extends TransactionOrVersionedTransaction<V>>(
tx: T,
): Promise<T> {
return this.adapter.signTransaction(tx);
}

signAllTransactions(transaction: Transaction[]): Promise<Transaction[]> {
signAllTransactions<T extends TransactionOrVersionedTransaction<V>>(
transaction: T[],
): Promise<T[]> {
return this.adapter.signAllTransactions(transaction);
}

Expand Down
4 changes: 3 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
"files": ["jest.config.mjs", ".eslintrc.cjs"],
"include": ["./**/*.test.ts"],
"references": [
{ "path": "packages/option-utils/" },
{ "path": "packages/tuple-utils/" },
{ "path": "packages/solana-contrib/" },
{ "path": "packages/anchor-contrib/" },
{ "path": "packages/chai-solana/" },
{ "path": "packages/option-utils/" },
{ "path": "packages/solana-contrib/" },
{ "path": "packages/stableswap-sdk/" },
{ "path": "packages/token-utils/" },
{ "path": "packages/tuple-utils/" },
Expand Down

0 comments on commit 95b5b7c

Please sign in to comment.