Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[experimental] Create a sham of legacy @solana/web3.js that can be used as a drop-in replacement for most use cases #1825

Open
steveluscher opened this issue Nov 11, 2023 · 0 comments
Labels
enhancement New feature or request

Comments

@steveluscher
Copy link
Collaborator

Motivation

You're an application that depends on a bunch of packages (mpl-token-metadata, @solana/wallet-adapter-react, etc.) and those packages themselves depend on @solana/web3.js (the legacy version).

Each of those packages use a tiny slice of web3.js. @solana/wallet-adapter-react for instance only does things like new PublicKey(), new Connection(), and publicKey.toBytes().

We could create a drop-in replacement for @solana/web3.js that only did the things that typical applications exercise; a sham, if you will.

This package would offer API compatible-ish versions of PublicKey, Connection et al, that used the new web3.js under the hood, or nothing at all.

Not a single line of your application should have to change and the legacy @solana/web3.js would just disappear from your bundle.

Example use case

#yolo replace all your legacy imports with that.

pnpm (package.json)

Using overrides.

"pnpm": {
  "overrides": {
    "@metaplex-foundation/mpl-token-metadata>@solana/web3.js": "npm:@solana/sham-web3.js"
  }
}

npm (package.json)

Using overrides.

"overrides": {
  "@metaplex-foundation/mpl-token-metadata": {
    "@solana/web3.js": "npm:@solana/sham-web3.js"
  }
}

Yarn (package.json)

Using resolutions.

"resolutions": {
  "@metaplex-foundation/mpl-token-metadata/@solana/web3.js": "npm:@solana/sham-web3.js"
}

Details

Here's an example of how you might implement a sham PublicKey.

import { getBase58Encoder } from '@solana/codecs-strings';

let memoizedBase58Encoder: ReturnType<typeof getBase58Encoder>;
function getMemoizedBase58Encoder() {
    if (!memoizedBase58Encoder) {
        memoizedBase58Encoder = getBase58Encoder();
    }
    return memoizedBase58Encoder;
}

class PublicKey {
    #address: string;
    constructor(address: string) {
        this.#address = address;
    }
    #getAddress() {
        return this.#address;
    }
    #getByteArray() {
        return getMemoizedBase58Encoder().encode(this.#address);
    }
    #getBuffer() {
        if (!__NODEJS__) {
            throw new Error('...');
        }
        return Buffer.from(this.#getByteArray());
    }
    encode = this.#getBuffer;
    equals(other: { toBase58: () => string }) {
        other.toBase58() === this.#address
    }
    toBase58 = this.#getAddress
    toBuffer = this.#getBuffer
    toBytes = this.#getByteArray
    toJSON = this.#getAddress
    toString = this.#getAddress
    get [Symbol.toStringTag]() {
        return `PublicKeyCompat(${this.#address})`;
    }
}

Playground link.

@steveluscher steveluscher added the enhancement New feature or request label Nov 11, 2023
steveluscher added a commit that referenced this issue Nov 20, 2023
# Preamble

Imagine that you depend on a module that itself depends on the legacy `@solana/web3.js`. This makes it difficult for you to remove the legacy library from your project.

The chances are, though, that module only needs a _fraction_ of what web3.js provides.

The goal of the sham – of which this PR is the first – is to provide drop-in replacements for just the things that a set list of known dependencies require. You should be able to hot-swap the sham in via npm `overrides` or yarn `resolutions` and thereby drop the legacy web3.js from your bundle.

# Summary

This PR introduces an interface compatible(-ish) `PublicKey` that you can use as a drop-in replacement for the one in `@solana/web3.js@1`

# Test Plan

```
cd packages/library-legacy-sham/
pnpm test:unit:browser
pnpm test:unit:node
```

See later diffs for a functional test plan where we actually drop the sham in to an actual application and see the results.

Addresses #1825.
steveluscher added a commit that referenced this issue Nov 20, 2023
# Preamble

Imagine that you depend on a module that itself depends on the legacy `@solana/web3.js`. This makes it difficult for you to remove the legacy library from your project.

The chances are, though, that module only needs a _fraction_ of what web3.js provides.

The goal of the sham – of which this PR is the first – is to provide drop-in replacements for just the things that a set list of known dependencies require. You should be able to hot-swap the sham in via npm `overrides` or yarn `resolutions` and thereby drop the legacy web3.js from your bundle.

# Summary

This PR introduces an interface compatible(-ish) `Keypair` that you can use as a drop-in replacement for the one in `@solana/web3.js@1`

# Test Plan

```
cd packages/library-legacy-sham/
pnpm test:unit:browser
pnpm test:unit:node
```

See later diffs for a functional test plan where we actually drop the sham in to an actual application and see the results.

Addresses #1825.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant