Prechádzať zdrojové kódy

Merge pull request #174 from metaplex-foundation/leo/umi-web3js-rework

Reworked and Merged Web3Js Adapter and Differences Page
Leonardo Donatacci 1 rok pred
rodič
commit
dbd3c25dc4

+ 1 - 2
src/components/products/umi/index.js

@@ -32,7 +32,7 @@ export const umi = {
               title: 'Metaplex Umi Plugins',
               href: '/umi/metaplex-umi-plugins',
             },
-            { title: 'Web3js Differences', href: '/umi/web3js-differences' },
+            { title: 'Web3js Differences and Adapters', href: '/umi/web3js-differences-and-adapters' },
           ],
         },
         {
@@ -54,7 +54,6 @@ export const umi = {
             { title: 'Serializers', href: '/umi/serializers' },
             { title: 'Storage', href: '/umi/storage' },
             { title: 'Transactions', href: '/umi/transactions' },
-            { title: 'Web3Js Adapters', href: '/umi/web3js-adapters' },
           ],
         },
       ],

+ 25 - 0
src/middleware.js

@@ -0,0 +1,25 @@
+import { NextResponse,  } from 'next/server'
+
+const redirectData = {
+  "/umi/web3js-adapters": {
+    "destination": "/umi/web3js-differences-and-adapters",
+    "permanent": true
+  },
+  "/umi/web3js-differences": {
+    "destination": "/umi/web3js-differences-and-adapters",
+    "permanent": true
+  },
+}
+
+export async function middleware(request) {
+  const pathname = request.nextUrl.pathname
+  const redirectEntry = redirectData[pathname]
+
+ 
+  if (redirectEntry ) {
+    const statusCode = redirectEntry.permanent ? 308 : 307
+    return NextResponse.redirect(request.nextUrl.origin + redirectEntry.destination, statusCode)
+  }
+ 
+  return NextResponse.next()
+}

+ 0 - 80
src/pages/umi/web3js-adapters.md

@@ -1,80 +0,0 @@
----
-title: Web3.js adapters
-metaTitle: Web3.js adapters | Umi
-description: Adapters to make Metaplex Umi work with Solana web3js.
----
-The `@solana/web3.js` library is currently widely used in the Solana ecosystem and defines its own types for public keys, transactions, instructions, etc.
-
-When creating Umi, we wanted to move away from the class-based types defined in `@solana/web3.js` and instead use a more functional approach by relying only on TypeScript types. This unfortunately means that not all types from `@solana/web3.js` are compatible with the ones provided by Umi and vice versa.
-
-To help with this issue, Umi provides a set of adapters that allows us to parse types to and from their Web3.js counterparts.
-
-To use them, you will first need to install the [`@metaplex-foundation/umi-web3js-adapters`](https://github.com/metaplex-foundation/umi/tree/main/packages/umi-web3js-adapters) package.
-
-```sh
-npm install @metaplex-foundation/umi-web3js-adapters
-```
-
-Then, you will have access to a bunch of helper methods to convert to and from Web3.js types.
-
-```ts
-// For public keys.
-fromWeb3JsPublicKey(myWeb3JsPublicKey)
-toWeb3JsPublicKey(myUmiPublicKey)
-
-// For keypairs.
-fromWeb3JsKeypair(myWeb3JsKeypair)
-toWeb3JsKeypair(myUmiKeypair)
-
-// For transactions.
-fromWeb3JsTransaction(myWeb3JsTransaction)
-toWeb3JsTransaction(myUmiTransaction)
-fromWeb3JsLegacyTransaction(myLegacyWeb3JsTransaction)
-toWeb3JsLegacyTransaction(myUmiTransaction)
-
-// For transaction messages.
-fromWeb3JsMessage(myWeb3JsTransactionMessage)
-toWeb3JsMessage(myUmiTransactionMessage)
-toWeb3JsMessageFromInput(myUmiTransactionInput)
-
-// For instructions.
-fromWeb3JsInstruction(myWeb3JsInstruction)
-toWeb3JsInstruction(myUmiInstruction)
-```
-
-Let's take a look at an example. Say you want to issue a vanilla token using the `@identity.com/solana-gateway-ts` library which relies on `@solana/web3.js`. It offers an `issueVanilla` function that creates an instruction but this isn't compatible with Umi.
-
-To go around this, you could create a wrapper function that converts the `issueVanilla` function into a Umi-compatible one. Precisely, this means we need to convert the returned instruction using `fromWeb3JsInstruction` and convert any public key passed into the function using `toWeb3JsPublicKey`.
-
-```ts
-import { issueVanilla as baseIssueVanilla } from '@identity.com/solana-gateway-ts'
-import {
-  fromWeb3JsInstruction,
-  toWeb3JsPublicKey,
-} from '@metaplex-foundation/umi-web3js-adapters'
-
-export const issueVanilla = (
-  gatewayTokenAccount: PublicKey,
-  payer: Signer,
-  gatekeeperAccount: PublicKey,
-  owner: PublicKey,
-  gatekeeperAuthority: Signer,
-  gatekeeperNetwork: PublicKey
-) =>
-  transactionBuilder([
-    {
-      instruction: fromWeb3JsInstruction(
-        baseIssueVanilla(
-          toWeb3JsPublicKey(gatewayTokenAccount),
-          toWeb3JsPublicKey(payer.publicKey),
-          toWeb3JsPublicKey(gatekeeperAccount),
-          toWeb3JsPublicKey(owner),
-          toWeb3JsPublicKey(gatekeeperAuthority.publicKey),
-          toWeb3JsPublicKey(gatekeeperNetwork)
-        )
-      ),
-      signers: [payer, gatekeeperAuthority],
-      bytesCreatedOnChain: 0,
-    },
-  ])
-```

+ 373 - 0
src/pages/umi/web3js-differences-and-adapters.md

@@ -0,0 +1,373 @@
+---
+title: Web3.js Differences and Adapters
+metaTitle: Umi - Web3.js Differences and Adapters
+description: Difference and Adapters to make Metaplex Umi work with Solana web3js.
+---
+
+The `@solana/web3.js` library is currently widely used in the Solana ecosystem and defines its own types for `Publickeys`, `Transactions`, `Instructions`, etc. 
+
+When creating `Umi`, we wanted to move away from the class-based types defined in `@solana/web3.js`. This unfortunately means that, although having the same or similar import names, not all types from `@solana/web3.js` are compatible with the ones provided by `Umi` and vice versa.
+
+To help with this issue, `Umi` provides a set of adapters that allows to parse types to and from their `Web3.js` counterparts and they can be found in the [`@metaplex-foundation/umi-web3js-adapters`](https://www.npmjs.com/package/@metaplex-foundation/umi-web3js-adapters) package.
+
+## Required Package and Imports
+
+The `umi-web3js-adapters` package includes all the helper methods needed to convert between Umi and Web3.js types. 
+
+While it's already included when you install the `@metaplex-foundation/umi` package, you can also install it separately using the following command:
+
+```
+npm i @metaplex-foundation/umi-web3js-adapters
+```
+
+**Here are the imports you’ll have access to:**
+
+```ts
+import { 
+  // Keypairs
+  fromWeb3JsKeypair, toWeb3JsKeypair,
+  // Publickey
+  fromWeb3JsPublicKey, toWeb3JsPublicKey,
+  // Instructions
+  fromWeb3JsInstruction, toWeb3JsInstruction,
+  // Legacy Transactions
+  fromWeb3JsLegacyTransaction, toWeb3JsLegacyTransaction,
+  // Versioned Transactions
+  fromWeb3JsTransaction, toWeb3JsTransaction, 
+  // Messages
+  fromWeb3JsMessage, toWeb3JsMessage, toWeb3JsMessageFromInput
+} from '@metaplex-foundation/umi-web3js-adapters';
+```
+
+## Publickeys
+
+Generating publickeys might seem similar at first sight, but there are some subtle differences between the packages. **Web3Js** uses a capital `P` and requires `new`, while the **Umi** version uses a lowercase `p`.
+
+### Umi
+```ts
+import { publicKey } from '@metaplex-foundation/umi';
+
+// Generate a new Umi Publickey
+const umiPublicKey = publicKey("11111111111111111111111111111111");
+```
+
+### Web3Js
+```ts
+import { PublicKey } from '@solana/web3.js';
+
+// Generate a new Web3Js Publickey
+const web3jsPublickey = new PublicKey("1111111111111111111111111111111111111111");
+```
+
+Next, let's look into how to use the adapters.
+
+### From Web3Js to Umi
+```ts
+import { PublicKey } from '@solana/web3.js';
+import { fromWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters';
+
+// Generate a new Publickey
+const web3jsPublickey = new PublicKey("1111111111111111111111111111111111111111");
+
+// Convert it using the UmiWeb3jsAdapters Package
+const umiPublicKey = fromWeb3JsPublicKey(web3jsPublickey);
+```
+
+### From Umi to Web3Js
+```ts
+import { publicKey } from '@metaplex-foundation/umi';
+import { toWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters';
+
+// Generate a new Publickey
+const umiPublicKey = publicKey("11111111111111111111111111111111");
+
+// Convert it using the UmiWeb3jsAdapters Package
+const web3jsPublickey = toWeb3JsPublicKey(umiPublicKey);
+```
+
+## Keypairs
+
+Generating keypairs is where the difference from Web3Js and Umi increase. With **Web3Js**, you can simply use `Keypair.generate()`, however, in **Umi**, you first need to create an Umi instance, which you'll use for most Umi and Metaplex-related operations.
+
+### Umi
+```ts
+import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
+import { generateSigner, createSignerFromKeypair } from '@metaplex-foundation/umi'
+
+// Generate a new Umi instance
+const umi = createUmi('https://api.devnet.solana.com')
+
+// Generate a new Umi keypair
+const umiKeypair = generateSigner(umi)
+
+// Or use an existing one
+const umiKeypair = umi.eddsa.createKeypairFromSecretKey(new Uint8Array(walletFile));
+```
+
+### Web3Js
+```ts
+import { Keypair } from '@solana/web3.js';
+
+// Generate a new Web3Js keypair
+const web3jsKeypair = Keypair.generate();
+
+// Or use an existing one
+const web3jsKeypair = Keypair.fromSecretKey(new Uint8Array(walletFile));
+```
+
+Next, let's look into how to use the adapters.
+
+### From Umi to Web3Js
+```ts
+import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
+import { generateSigner } from '@metaplex-foundation/umi'
+import { toWeb3JsKeypair } from '@metaplex-foundation/umi-web3js-adapters';
+
+// Generate a new Umi instance
+const umi = createUmi('https://api.devnet.solana.com')
+
+// Generate a new keypair
+const umiKeypair = generateSigner(umi)
+
+// Convert it using the UmiWeb3jsAdapters Package
+const web3jsKeypair = toWeb3JsKeypair(umiKeypair);
+```
+
+### From Web3Js to Umi
+```ts
+import { Keypair } from '@solana/web3.js';
+import { fromWeb3JsKeypair } from '@metaplex-foundation/umi-web3js-adapters';
+
+// Generate a new keypair
+const web3jsKeypair = Keypair.generate();
+
+// Convert it using the UmiWeb3jsAdapters Package
+const umiKeypair = fromWeb3JsKeypair(web3jsKeypair);
+```
+
+## Instructions
+
+When creating instructions, the key difference with Umi is that you must first create an Umi instance (as with `Keypairs`). Additionally, `getInstructions()` returns an array of instructions instead of a single one.
+
+For most use cases, handling individual instructions isn't necessary anyway, as this can be simplified using other helpers and transaction builders.
+
+### Umi
+```ts
+import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
+import { transferSol } from '@metaplex-foundation/mpl-toolbox';
+
+// Generate a new Umi instance
+const umi = createUmi('https://api.devnet.solana.com').use(mplCore())
+
+// Create a new instruction (like a core nft transfer)
+// get instructions will give you an Array of instructions
+const umiInstructions = transferSol(umi, {...TransferParams}).getInstructions();
+```
+
+### Web3Js
+```ts
+import { SystemProgram } from '@solana/web3.js';
+
+// Create a new instruction (like a lamport transfer)
+const web3jsInstruction = SystemProgram.transfer({...TransferParams})
+```
+
+Next, let's look into how to use the adapters.
+
+### From Umi to Web3Js
+```ts
+import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
+import { transferSol } from '@metaplex-foundation/mpl-toolbox';
+import { toWeb3JsInstruction } from '@metaplex-foundation/umi-web3js-adapters';
+
+// Generate a new Umi instance
+const umi = createUmi('https://api.devnet.solana.com').use(mplCore())
+
+// Create a new instruction (like a core nft transfer)
+const umiInstruction = transferSol(umi, {...TransferParams}).getInstructions();
+
+// Convert it using the UmiWeb3jsAdapters Package
+const web3jsInstruction = umiInstruction.map(toWeb3JsInstruction);
+```
+
+### From Web3Js to Umi
+```ts
+import { SystemProgram } from '@solana/web3.js';
+import { fromWeb3JsInstruction } from '@metaplex-foundation/umi-web3js-adapters';
+
+// Generate a new Umi instance
+const umi = createUmi('https://api.devnet.solana.com')
+
+// Create a new instruction (like a lamport transfer)
+const web3jsInstruction = SystemProgram.transfer({...TransferParams})
+
+// Convert it using the UmiWeb3jsAdapters Package
+const umiInstruction = fromWeb3JsInstruction(web3jsInstruction);
+```
+
+## Transactions
+
+The Solana runtime supports two transaction versions:
+- Legacy Transaction: Older transaction format with no additional benefit
+- 0 / Versioned Transaction: Added support for Address Lookup Tables
+
+**Note**: if you're not familiar with the concept of Versioned Transactions, read more about it [here](https://solana.com/en/docs/advanced/versions)
+
+For `umi` and `umi-web3js-adapters` we added support for both transaction types! 
+
+### Umi
+```ts
+import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
+import { transferSol } from '@metaplex-foundation/mpl-toolbox';
+// Generate a new Umi instance
+const umi = createUmi('https://api.devnet.solana.com').use(mplCore())
+
+// Create a new Umi Legacy Transaction
+const umiTransaction = transferSol(umi, {...TransferParams}).useLegacyVersion();
+
+// Create a new Umi Versioned Transaction
+const umiVersionedTransaction = transferSol(umi, {...TransferParams}).useV0().build(umi)
+```
+
+### Web3Js
+```ts
+import { Transaction, VersionedTransaction, TransactionMessage, Connection, clusterApiUrl, SystemProgram } from '@solana/web3.js';
+
+// Create a new Web3Js Legacy Transaction
+const web3jsTransaction = new Transaction().add(SystemProgram.transfer({...TransferParams}));
+
+// Create a new Web3Js Versioned Transaction
+const instructions = [SystemProgram.transfer({...TransferParams})];
+
+const connection = new Connection(clusterApiUrl("devnet"));
+const blockhash = await connection.getLatestBlockhash().then(res => res.blockhash);
+
+const messageV0 = new TransactionMessage({
+  payerKey: payer.publicKey,
+  recentBlockhash: blockhash,
+  instructions,
+}).compileToV0Message();
+
+const web3jsVersionedTransaction = new VersionedTransaction(messageV0);
+```
+
+Next, let's look into how to use the adapters.
+
+### From Umi to Web3Js
+```ts
+import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
+import { transferSol } from '@metaplex-foundation/mpl-toolbox';
+import { toWeb3JsLegacyTransaction, toWeb3JsTransaction } from '@metaplex-foundation/umi-web3js-adapters';
+
+// Generate a new Umi instance
+const umi = createUmi('https://api.devnet.solana.com').use(mplCore())
+
+// Create a new Legacy Transaction
+const umiTransaction = transferSol(umi, {...TransferParams}).useLegacyVersion();
+
+// Convert it using the UmiWeb3jsAdapters Package
+const web3jsTransaction = toWeb3JsTransaction(umiTransaction);
+
+/// Versioned Transactions ///
+
+// Create a new Versioned Transaction
+const umiVersionedTransaction = transferSol(umi, {...TransferParams}).useV0().build(umi)
+
+// Convert it using the UmiWeb3jsAdapters Package
+const web3jsVersionedTransaction = toWeb3JsTransaction(umiVersionedTransaction);
+```
+
+### From Web3Js to Umi
+```ts
+import { Transaction, VersionedTransaction, TransactionMessage, Connection, clusterApiUrl, SystemProgram } from '@solana/web3.js';
+import { fromWeb3JsLegacyTransaction, fromWeb3JsTransaction } from '@metaplex-foundation/umi-web3js-adapters';
+
+// Create a new Legacy Transaction
+const web3jsTransaction = new Transaction().add(SystemProgram.transfer({...TransferParams}));
+
+// Convert it using the UmiWeb3jsAdapters Package
+const umiTransaction = fromWeb3JsLegacyTransaction(web3jsTransaction);
+
+/// Versioned Transactions ///
+
+// Create a new Versioned Transaction
+const web3jsVersionedTransaction = new VersionedTransaction(...messageV0Params);
+
+// Convert it using the UmiWeb3jsAdapters Package
+const umiVersionedTransaction = fromWeb3JsTransaction(web3jsVersionedTransaction);
+```
+
+
+## Messages 
+
+We've already covered creating messages during versioned transaction creation. Let's review it again.
+
+### Umi
+```ts
+import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
+import { transfer, mplCore } from '@metaplex-foundation/mpl-core'
+
+// Generate a new Umi instance
+const umi = createUmi('https://api.devnet.solana.com').use(mplCore())
+
+// Create a new Umi Message
+const blockhash = await umi.rpc.getLatestBlockhash()
+
+const instructions = transfer(umi, {...TransferParams}).getInstructions()
+
+const umiVersionedTransaction = umi.transactions.create({
+  version: 0,
+  payer: frontEndSigner.publicKey,
+  instructions,
+  blockhash: blockhash.blockhash,
+});
+
+const umiMessage = umiVersionedTransaction.message
+```
+
+### Web3Js
+```ts
+import { TransactionMessage, Connection, clusterApiUrl, SystemProgram } from '@solana/web3.js';
+
+// Create a new Web3Js Message
+const connection = new Connection(clusterApiUrl("devnet"));
+const minRent = await connection.getMinimumBalanceForRentExemption(0);
+const blockhash = await connection.getLatestBlockhash().then(res => res.blockhash);
+
+const instructions = [SystemProgram.transfer({...TransferParams})];
+
+const Web3JsMessage = new TransactionMessage({
+  payerKey: payer.publicKey,
+  recentBlockhash: blockhash,
+  instructions,
+}).compileToV0Message();
+```
+
+Next, let's look into how to use the adapters.
+
+### From Umi to Web3Js
+```ts
+import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
+import { toWeb3JMessage } from '@metaplex-foundation/umi-web3js-adapters';
+
+// Generate a new Umi instance
+const umi = createUmi('https://api.devnet.solana.com').use(mplCore())
+
+// Create a new Versioned Transaction
+const umiMessage = umi.transactions.create({...createParams}).message;
+
+// Convert it using the UmiWeb3jsAdapters Package
+const web3jsMessage = toWeb3JMessage(umiMessage);
+```
+
+### From Web3Js to Umi
+```ts
+import { TransactionMessage } from '@solana/web3.js';
+import { fromWeb3JMessage } from '@metaplex-foundation/umi-web3js-adapters';
+
+// Create a new Versioned Transaction
+const Web3JsMessage = new TransactionMessage({...createMessageParams}).compileToV0Message();
+
+// Convert it using the UmiWeb3jsAdapters Package
+const umiMessage = fromWeb3JMessage(Web3JsMessage);
+```

+ 0 - 103
src/pages/umi/web3js-differences.md

@@ -1,103 +0,0 @@
----
-title: Umi and Web3js Differences
-metaTitle: Umi and Web3js Differences | Umi
-description: Differences between Metaplex Umi and Solana web3js.
----
-
-## Differences
-
-When using Umi you may come across some differences between Umi and solana web3js.
-
-Although having the same or similar import names these function differently and are not compatible between the two librarys out the box.
-
-### PublicKeys
-
-{% dialect-switcher title="Umi PublicKey" %}
-{% dialect title="JavaScript" id="js" %}
-```ts
-import { publicKey } from '@metaplex-foundation/umi'
-const publicKey = publicKey('tst24HZ6pbcnraCv4r8acexfgXvyQwMSRgZRCg9gEX1')
-```
-{% /dialect %}
-{% /dialect-switcher %}
-{% seperator h="6" /%}
-{% dialect-switcher title="Solana Web3js PublicKey" %}
-{% dialect title="JavaScript" id="js" %}
-```js
-import { PublicKey } from '@solana/web3js'
-const publicKey = new PublicKey('tst24HZ6pbcnraCv4r8acexfgXvyQwMSRgZRCg9gEX1')
-```
-{% /dialect %}
-{% /dialect-switcher %}
-
-These are just basic examples. To learn more about Umi's keypairs check out [PublicKeys and Signers](/umi/public-keys-and-signers). There are also converters between both Umi and web3js [Web3Js Adapters](/umi/web3js-adapters)
-
-### Keypairs
-
-{% dialect-switcher title="Umi Keypair" %}
-{% dialect title="JavaScript" id="js" %}
-```js
-const umi = createUmi(...)
-const keypair = umi.eddsa.createKeypairFromSecretKey(new Uint8Array(secretKey))
-
-```
-{% /dialect %}
-{% /dialect-switcher %}
-
-{% seperator h="6" /%}
-
-{% dialect-switcher title="Web3js Keypair" %}
-{% dialect title="JavaScript" id="js" %}
-```js
-import { Keypair } from '@solana/web3js'
-const publicKey = Keypair.fromSecretKey(new Uint8Array(JSON.parse(Wallet.DEV1)))
-```
-{% /dialect %}
-{% /dialect-switcher %}
-
-These are just basic examples. To learn more about Umi's keypairs check out [PublicKeys and Signers](/umi/public-keys-and-signers). There are also converters between both Umi and web3js keypair types [Web3Js Adapters](/umi/web3js-adapters)
-
-### Transactions
-
-{% dialect-switcher title="Umi Transaction" %}
-{% dialect title="JavaScript" id="js" %}
-```js
-const blockhash = await umi.rpc.getLatestBlockhash()
-
-const transaction = const tx = umi.transactions.create({
-    version: 0,
-    payer: umi.identity.publicKey,
-    instructions: ix,
-    blockhash: blockhash.blockhash,
-  });
-
-await umi.rpc.sendTransaction(tx)
-```
-{% /dialect %}
-{% /dialect-switcher %}
-
-{% seperator h="6" /%}
-
-{% dialect-switcher title="Web3js Transaction" %}
-{% dialect title="JavaScript" id="js" %}
-
-```js
-const wallet = useWallet()
-
-const messageV0 = new TransactionMessage({
-  payerKey: SIGNER_WALLET.publicKey,
-  recentBlockhash: latestBlockhash.blockhash,
-  instructions: txInstructions,
-}).compileToV0Message()
-
-const tx = new VersionedTransaction(messageV0)
-
-// send via useWallet hook
-await wallet.sendTransaction(tx)
-//or send via connection
-await connection.sendTransaction(tx)
-```
-{% /dialect %}
-{% /dialect-switcher %}
-
-These are just basic examples. To learn more about Umi's Transiactions check out [Transactions](/umi/transactions). There are also converters between both Umi and web3js Transaction types [Web3Js Adapters](/umi/web3js-adapters)