diff --git a/src/components/products/guides/index.js b/src/components/products/guides/index.js index 1331f4b44..37fd1a8ee 100644 --- a/src/components/products/guides/index.js +++ b/src/components/products/guides/index.js @@ -39,7 +39,7 @@ export const guides = { title: 'Solana Transaction Fundamentals', href: '/solana/solana-transaction-fundamentals', created: '02-04-2026', - updated: null, + updated: '09-21-2026', }, { title: 'Solana Programs', diff --git a/src/components/products/umi/index.js b/src/components/products/umi/index.js index 7fae6f81c..de8cf7ccb 100644 --- a/src/components/products/umi/index.js +++ b/src/components/products/umi/index.js @@ -97,6 +97,12 @@ export const umi = { { title: 'Guides', links: [ + { + title: 'Migrating from V0 to V1 Transactions', + href: '/dev-tools/umi/guides/migrate-to-transaction-v1', + created: '2026-09-21', + updated: null, // null means it's never been updated + }, { title: 'Optimal transaction landing', href: '/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees', @@ -151,6 +157,7 @@ export const umi = { 'Priority Fees and Compute Managment': 'Priority Fees and Compute Managment', 'Address Lookup Table': 'Address Lookup Table', 'Transaction Memo': 'Transaction Memo', + 'Migrating from V0 to V1 Transactions': 'Migrating from V0 to V1 Transactions', 'Optimal transaction landing': 'Optimal transaction landing', 'Serializing and Deserializing Transactions': 'Serializing and Deserializing Transactions', 'RPC': 'RPC', diff --git a/src/pages/en/dev-tools/umi/getting-started/index.md b/src/pages/en/dev-tools/umi/getting-started/index.md index 7005af689..31c9d2824 100644 --- a/src/pages/en/dev-tools/umi/getting-started/index.md +++ b/src/pages/en/dev-tools/umi/getting-started/index.md @@ -8,11 +8,11 @@ description: A Javascript Framework for Solana. To use Umi you need to install Umi and all the external plugins you'll want to use. Alternatively, if you don't need a specific plugin, you can install the default bundle that includes a set of plugins that's suitable for most use cases. -**Note**: since the default bundle relies on web3.js for some of the interfaces you'll need to install that package as well. +**Note**: Since the default bundle relies on Web3.js for some interfaces, you need to install that package as well. Umi 1.6.0 requires `@solana/web3.js` 1.99.0 or later for V1 transaction support. ### Required Packages -{% packagesUsed packages=["umi", "umiDefaults", "@solana/web3.js@1"] type="npm" /%} +{% packagesUsed packages=["umi", "umiDefaults", "@solana/web3.js"] type="npm" /%} To install them, use the following commands: @@ -25,7 +25,7 @@ npm i @metaplex-foundation/umi-bundle-defaults ``` ``` -npm i @solana/web3.js@1 +npm i @solana/web3.js@^1.99.0 ``` ### For library authors diff --git a/src/pages/en/dev-tools/umi/guides/index.md b/src/pages/en/dev-tools/umi/guides/index.md index 10d1247d4..def02d21a 100644 --- a/src/pages/en/dev-tools/umi/guides/index.md +++ b/src/pages/en/dev-tools/umi/guides/index.md @@ -2,14 +2,38 @@ title: Umi Guides metaTitle: Guides | Umi Guides description: How-to guides for Metaplex's Umi client wrapper and RPC client. +keywords: + - Umi guides + - Solana JavaScript SDK + - Umi transaction v1 +about: + - Umi + - Solana Development +proficiencyLevel: Beginner +created: '07-01-2024' +updated: '09-21-2026' --- -The following Guides for Umi are currently available: +## Summary + +Umi guides provide task-focused instructions for transactions, serialization, compute configuration, and priority fees. + +- Migrate transaction builders from V0 to V1. +- Optimize V1 compute units and priority fees. +- Serialize transactions across frontend and backend environments. +- Use the main [Umi documentation](/dev-tools/umi) for concepts and API features. {% quick-links %} +{% quick-link title="Migrating from V0 to V1 Transactions" icon="CodeBracketSquare" href="/dev-tools/umi/guides/migrate-to-transaction-v1" description="Adopt V1 transactions, migrate compute budgets, and check wallet and Address Lookup Table compatibility." /%} + {% quick-link title="Optimal Transaction landing" icon="CodeBracketSquare" href="/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees" description="Improve your transactions by adding the optimal Compute Units (CU) and priority fees." /%} {% quick-link title="Serializing and Deserializing Transactions" icon="CodeBracketSquare" href="/dev-tools/umi/guides/serializing-and-deserializing-transactions" description="Learn how to Serialize and Deserialize Transactions to move them across different environments while using the Metaplex Umi client." /%} {% /quick-links %} + +## Notes + +- V1 transaction examples require Umi 1.6.0 or later and `@solana/web3.js` 1.99.0 or later. +- V1 transactions do not support Address Lookup Tables. diff --git a/src/pages/en/dev-tools/umi/guides/migrate-to-transaction-v1.md b/src/pages/en/dev-tools/umi/guides/migrate-to-transaction-v1.md new file mode 100644 index 000000000..17a715ed1 --- /dev/null +++ b/src/pages/en/dev-tools/umi/guides/migrate-to-transaction-v1.md @@ -0,0 +1,268 @@ +--- +title: Migrating from V0 to V1 Transactions +metaTitle: Migrating from V0 to V1 Transactions | Umi +description: Migrate Umi transaction builders and direct transaction creation from Solana V0 transactions to V1 transactions, including compute budgets, priority fees, and wallet compatibility. +keywords: + - Umi transaction v1 + - Solana transaction v1 + - Umi v0 migration + - TransactionV1Config + - useV1 + - setTransactionConfig + - SIMD-0385 +about: + - Umi + - Solana Transaction V1 + - Transaction Migration +proficiencyLevel: Intermediate +programmingLanguage: + - JavaScript + - TypeScript +created: '09-21-2026' +updated: '09-21-2026' +howToSteps: + - Upgrade Umi packages to version 1.6.0 or later and web3.js to version 1.99.0 or later + - Select V1 per transaction builder or as the application default + - Replace Compute Budget instructions with a TransactionV1Config + - Keep transactions that require Address Lookup Tables on V0 + - Verify that every connected wallet supports V1 transactions before signing +howToTools: + - Umi 1.6.0 or later + - web3.js 1.99.0 or later + - Solana RPC +faqs: + - q: Does Umi use V1 transactions by default? + a: No. Umi 1.6.0 keeps V0 as the default for backward compatibility. Call useV1 on a transaction builder or set defaultTransactionVersion to 1 when creating Umi. + - q: Can a Umi V1 transaction use an Address Lookup Table? + a: No. V1 transactions do not support Address Lookup Tables. Keep any transaction that requires an Address Lookup Table on V0. + - q: Can a V1 transaction contain Compute Budget program instructions? + a: No. Umi rejects V1 transaction builders that contain Compute Budget instructions. Use setTransactionConfig to set the compute unit limit, total priority fee, loaded accounts data size limit, or heap size. + - q: Is the V1 transaction priority fee a price per compute unit? + a: No. TransactionV1Config.priorityFee is the total priority fee as a SolAmount. Convert a micro-lamport price by multiplying it by the compute unit limit, dividing by 1,000,000, and rounding up to lamports. + - q: Do all Solana wallets support V1 transactions? + a: No. Umi can serialize V1 transactions for wallet adapters, but the connected wallet must accept and sign transaction version 1. Check wallet support before making V1 the application-wide default. +--- + +Migrate Umi applications from V0 to [V1 transactions](https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0385-transaction-v1.md) to use larger transactions and configure the compute budget directly on the transaction message. {% .lead %} + +{% callout title="What You'll Migrate" %} +This guide converts a Umi V0 transaction builder to V1, replaces Compute Budget instructions with `TransactionV1Config`, configures V1 globally, and identifies transactions that must remain on V0. +{% /callout %} + +## Summary + +Umi 1.6.0 adds opt-in support for V1 transactions through `useV1()`, `defaultTransactionVersion: 1`, and `version: 1` on direct transaction inputs. + +- V1 raises the serialized transaction limit from 1,232 to 4,096 bytes. +- V1 stores compute limits and the total priority fee in `TransactionV1Config`. +- V1 does not support Address Lookup Tables or Compute Budget instructions. +- Umi still defaults to V0, and connected wallets must support V1. + +## Quick Start + +Select V1 on the transaction builder and replace Compute Budget instructions with `setTransactionConfig`. + +1. Upgrade to Umi 1.6.0 or later and `@solana/web3.js` 1.99.0 or later. +2. Add `.useV1()` to the transaction builder. +3. Remove `setComputeUnitLimit` and `setComputeUnitPrice` instructions. +4. Add `.setTransactionConfig({ computeUnitLimit, priorityFee })`. +5. Test V1 signing with every wallet supported by the application. + +**Jump to:** [Prerequisites](#prerequisites) · [V0 and V1 Differences](#differences-between-v0-and-v1-transactions) · [Builder Migration](#migrating-a-transaction-builder-to-v1) · [Application Default](#setting-v1-as-the-application-default) · [Direct Creation](#migrating-direct-transaction-creation-to-v1) · [Address Lookup Tables](#keeping-address-lookup-table-transactions-on-v0) · [Common Errors](#common-v1-migration-errors) · [FAQ](#faq) + +## Prerequisites + +V1 migration requires compatible Umi, Web3.js, RPC, and wallet versions. + +| Component | Requirement | +|-----------|-------------| +| Umi packages | 1.6.0 or later | +| `@solana/web3.js` | 1.99.0 or later | +| Solana clusters | V1 active on mainnet-beta, devnet, and testnet | +| Wallet | Must accept and sign transaction version `1` | + +{% callout type="warning" %} +Do not enable V1 globally until every connected wallet path supports transaction version `1`. Umi serializes the transaction for wallet adapters but cannot make an incompatible wallet sign it. +{% /callout %} + +## Differences Between V0 and V1 Transactions + +V1 increases the transaction size limit but does not support V0 Address Lookup Tables or Compute Budget instructions. + +| Capability | V0 | V1 | +|------------|----------------|----------------| +| Serialized size limit | 1,232 bytes | 4,096 bytes | +| Address lookup tables | Supported | Not supported | +| Compute unit limit | Compute Budget instruction | `transactionConfig.computeUnitLimit` | +| Priority fee | Micro-lamports per compute unit | Total `SolAmount` in `transactionConfig.priorityFee` | +| Default in Umi 1.6.0 | Yes | No, you must opt in | +| Builder selector | `useV0()` | `useV1()` | + +V1 is most useful when a transaction exceeds the V0 size limit without relying on an Address Lookup Table. + +## Migrating a Transaction Builder to V1 + +A V0 transaction builder migrates to V1 by replacing Compute Budget instructions with `useV1()` and `setTransactionConfig()`. + +### V0 Transaction Builder Before Migration + +The V0 transaction builder expresses the compute unit limit and price as instructions. + +```typescript {% title="transaction-v0.ts" %} +import { transactionBuilder } from '@metaplex-foundation/umi' +import { + setComputeUnitLimit, + setComputeUnitPrice, + transferSol, +} from '@metaplex-foundation/mpl-toolbox' + +await transactionBuilder() + .add(setComputeUnitLimit(umi, { units: 600_000 })) + .add(setComputeUnitPrice(umi, { microLamports: 1_000 })) + .add(transferSol(umi, transferArgs)) + .sendAndConfirm(umi) +``` + +### V1 Transaction Builder After Migration + +The V1 transaction builder expresses the compute unit limit and total priority fee in the transaction message. + +```typescript {% title="transaction-v1.ts" %} +import { lamports, transactionBuilder } from '@metaplex-foundation/umi' +import { transferSol } from '@metaplex-foundation/mpl-toolbox' + +await transactionBuilder() + .add(transferSol(umi, transferArgs)) + .useV1() + .setTransactionConfig({ + computeUnitLimit: 600_000, + priorityFee: lamports(600), + }) + .sendAndConfirm(umi) +``` + +The `600` lamport total fee equals `600,000 × 1,000 ÷ 1,000,000`. Round up when the conversion does not produce a whole lamport. + +{% callout type="note" %} +`setTransactionConfig()` replaces the complete config. Include every custom v1 setting in the same call instead of calling it repeatedly with individual fields. +{% /callout %} + +## Setting V1 as the Application Default + +Setting `defaultTransactionVersion: 1` makes all transaction builders use V1 unless a builder explicitly selects another version. + +```typescript {% title="umi.ts" %} +import { createUmi } from '@metaplex-foundation/umi-bundle-defaults' + +const umi = createUmi('https://api.mainnet-beta.solana.com', { + defaultTransactionVersion: 1, +}) +``` + +This option also affects builders returned by Metaplex program libraries. A builder that calls `useV0()` still overrides the application default. + +Applications that install the transaction factory directly can configure the plugin instead: + +```typescript {% title="umi-with-custom-plugins.ts" %} +import { web3JsTransactionFactory } from '@metaplex-foundation/umi-transaction-factory-web3js' + +umi.use(web3JsTransactionFactory({ defaultTransactionVersion: 1 })) +``` + +## Migrating Direct Transaction Creation to V1 + +Direct `umi.transactions.create()` calls must set `version: 1` and provide explicit nonzero runtime limits. + +```typescript {% title="create-transaction-v1.ts" %} +const transaction = umi.transactions.create({ + version: 1, + blockhash: (await umi.rpc.getLatestBlockhash()).blockhash, + instructions: [myInstruction], + payer: umi.payer.publicKey, + transactionConfig: { + computeUnitLimit: 200_000, + loadedAccountsDataSizeLimit: 64 * 1024 * 1024, + }, +}) +``` + +`TransactionBuilder` supplies legacy-equivalent defaults for omitted compute and loaded-account limits. The low-level `create()` method does not; an omitted limit is treated as zero by the runtime. + +## Configuring V1 Transaction Limits + +`TransactionV1Config` controls compute, account data, heap size, and the total priority fee. + +| Field | Meaning | Valid range or behavior | +|-------|---------|-------------------------| +| `computeUnitLimit` | Maximum compute units | Integer from `0` through `1,400,000` | +| `priorityFee` | Total priority fee | `SolAmount`, usually created with `lamports(...)` | +| `loadedAccountsDataSizeLimit` | Maximum loaded account data | Up to 64 MiB | +| `heapSize` | Program heap frame size | 32,768 through 262,144 bytes in 1,024-byte increments | + +The builder defaults `computeUnitLimit` to `min(200,000 × instruction count, 1,400,000)` and `loadedAccountsDataSizeLimit` to 64 MiB when those fields are omitted. + +## Keeping Address Lookup Table Transactions on V0 + +Transactions that require [Address Lookup Tables](/dev-tools/umi/toolbox/address-lookup-table) must remain on V0. + +```typescript {% title="transaction-v0-with-lookup-table.ts" %} +const builder = transactionBuilder() + .add(myInstruction) + .useV0() + .setAddressLookupTables([myLookupTable]) +``` + +Do not remove an Address Lookup Table merely to force a transaction onto V1. Compare the compiled account list and serialized size, then use the format that satisfies the transaction's requirements. + +## Updating Custom Umi Integrations + +Custom transaction factories and exhaustive version handling must add V1 support when upgrading to Umi 1.6.0. + +- Implement `getDefaultVersion()` on custom `TransactionFactoryInterface` implementations. +- Add a `1` case to code that exhaustively switches over `TransactionVersion`. +- Add `version: 0` to direct V0 `TransactionInput` objects because the V0 version field is now required. +- Inspect `transaction.message.version` when reading transactions; V1 messages include `transactionConfig`. + +Umi's RPC integration requests `maxSupportedTransactionVersion: 1`, so `umi.rpc.getTransaction()` can fetch V1 transactions. + +## Common V1 Migration Errors + +Umi rejects incompatible builder combinations before sending the transaction. + +| Error | Cause | Fix | +|-------|-------|-----| +| `V1 transactions ignore ComputeBudget instructions. Set the compute budget with setTransactionConfig instead.` | A V1 transaction builder contains `setComputeUnitLimit`, `setComputeUnitPrice`, or another Compute Budget instruction | Remove the instruction and use `setTransactionConfig()` | +| `Address lookup tables are not supported by V1 transactions.` | A V1 transaction builder has one or more Address Lookup Tables | Keep the builder on V0 or remove the lookup-table requirement | +| `Transaction configs are only supported by V1 transactions.` | A legacy or V0 transaction builder calls `setTransactionConfig()` | Call `useV1()` or use Compute Budget instructions on V0 | +| Wallet rejects or cannot deserialize the transaction | The wallet does not support transaction version `1` | Keep that wallet flow on V0 until the wallet adds V1 support | +| Transaction fails with an insufficient compute budget after direct creation | `create()` received no `computeUnitLimit` | Set a nonzero `transactionConfig.computeUnitLimit` | + +## Notes + +- V1 is opt-in in Umi 1.6.0; the default remains V0 for backward compatibility. +- V1 became active on Solana mainnet-beta in epoch 1035 on September 15, 2026. +- Sending and simulation use base64 encoding, which supports V1 transactions larger than 1,232 bytes. +- Umi validates the compute unit limit and heap size before serialization. +- The implementation and compatibility details are documented in [metaplex-foundation/umi#216](https://github.com/metaplex-foundation/umi/pull/216). + +## FAQ + +### Does Umi Use V1 Transactions by Default? + +Umi 1.6.0 keeps V0 as the default for backward compatibility. Call `useV1()` on a transaction builder or set `defaultTransactionVersion: 1` when creating Umi. + +### Can a Umi V1 Transaction Use an Address Lookup Table? + +V1 transactions do not support Address Lookup Tables. Keep any transaction that requires an Address Lookup Table on V0. + +### Can a V1 Transaction Contain Compute Budget Program Instructions? + +Umi rejects V1 transaction builders that contain Compute Budget instructions. Use `setTransactionConfig()` to set the compute unit limit, total priority fee, loaded accounts data size limit, or heap size. + +### Is the V1 Transaction Priority Fee a Price per Compute Unit? + +`TransactionV1Config.priorityFee` is the total priority fee as a `SolAmount`, not a price per compute unit. Convert a micro-lamport price by multiplying it by the compute unit limit, dividing by 1,000,000, and rounding up to lamports. + +### Do All Solana Wallets Support V1 Transactions? + +Wallet support for transaction version `1` is not universal. Umi can serialize V1 transactions for wallet adapters, but the connected wallet must accept and sign the transaction. diff --git a/src/pages/en/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees.md b/src/pages/en/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees.md index 387cbfb25..cfe9a72d9 100644 --- a/src/pages/en/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees.md +++ b/src/pages/en/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees.md @@ -2,11 +2,42 @@ title: Optimal transaction landing using Compute Units (CU) and priority fees metaTitle: Umi - Optimal transaction landing using Compute Units (CU) and priority fees description: Learn how to optimize your Solana transactions by calculating and setting appropriate Compute Units (CU) and priority fees. +keywords: + - Umi transaction v1 + - compute units + - priority fees + - transaction optimization +about: + - Umi + - Solana Transaction V1 + - Priority Fees +proficiencyLevel: Intermediate +programmingLanguage: + - JavaScript + - TypeScript created: '12-02-2024' -updated: '12-02-2024' +updated: '09-21-2026' --- -When sending transactions on Solana, optimizing two key parameters can significantly improve your transaction's success rate and cost-effectiveness: +## Summary + +Umi V1 transactions use simulation to estimate compute consumption and store the compute limit and total priority fee in `TransactionV1Config`. + +- Simulate with a 1,400,000 compute unit limit. +- Add a safety margin to the consumed units. +- Estimate the market price in micro-lamports per compute unit. +- Convert the estimate to a total lamport fee before calling `setTransactionConfig()`. + +When sending transactions on Solana, optimizing two key parameters can significantly improve your transaction's success rate and cost-effectiveness. + +## Quick Start + +Estimate the V1 compute limit and total priority fee before sending the transaction. + +1. [Estimate the priority fee](#priority-fees) from recent fees paid for the transaction's writable accounts. +2. [Simulate the transaction](#compute-unit-limit) with the maximum V1 compute limit. +3. [Apply the estimated values](#implementation-guide) with `setTransactionConfig()`. +4. [Run the complete SOL transfer example](#full-example-for-sol-transfer). ## Priority Fees @@ -160,16 +191,20 @@ export const getRequiredCU = async ( return DEFAULT_COMPUTE_UNITS; } - // Add safety buffer to estimated compute units - return Math.ceil(unitsConsumed * BUFFER_FACTOR); // Step 3: use the buffer + // Add a safety buffer without exceeding the V1 maximum. + const bufferedUnits = Math.ceil(unitsConsumed * BUFFER_FACTOR); + if (bufferedUnits > 1_400_000) { + throw new Error( + `Transaction requires ${bufferedUnits} compute units after buffering, so it cannot fit within the V1 maximum of 1,400,000. Split it into multiple transactions.` + ); + } + return bufferedUnits; // Step 3: use the buffer }; - const withCU = baseTransaction.prepend( - setComputeUnitPrice(umi, { microLamports: priorityFee }) - ).prepend( - setComputeUnitLimit(umi, { units: 1400000 }) - ); + const withCU = baseTransaction + .useV1() + .setTransactionConfig({ computeUnitLimit: 1_400_000 }); // Step 8: Calculate optimal compute unit limit console.log("Estimating required compute units..."); @@ -186,6 +221,7 @@ Following the code above and introducing some boilerplate to create the Umi inst ```js import { createUmi } from "@metaplex-foundation/umi-bundle-defaults"; import { + lamports, sol, publicKey, Transaction, @@ -196,8 +232,6 @@ import { } from "@metaplex-foundation/umi"; import { transferSol, - setComputeUnitLimit, - setComputeUnitPrice, mplToolbox, } from "@metaplex-foundation/mpl-toolbox"; import { base58, base64 } from "@metaplex-foundation/umi/serializers"; @@ -301,8 +335,14 @@ export const getRequiredCU = async ( return DEFAULT_COMPUTE_UNITS; } - // Add safety buffer to estimated compute units - return Math.ceil(unitsConsumed * BUFFER_FACTOR); + // Add a safety buffer without exceeding the V1 maximum. + const bufferedUnits = Math.ceil(unitsConsumed * BUFFER_FACTOR); + if (bufferedUnits > 1_400_000) { + throw new Error( + `Transaction requires ${bufferedUnits} compute units after buffering, so it cannot fit within the V1 maximum of 1,400,000. Split it into multiple transactions.` + ); + } + return bufferedUnits; }; /** @@ -339,23 +379,25 @@ const example = async () => { const priorityFee = await getPriorityFee(umi, baseTransaction); // Step 7: Create intermediate transaction for compute unit estimation - const withCU = baseTransaction.prepend( - setComputeUnitPrice(umi, { microLamports: priorityFee }) - ).prepend( - setComputeUnitLimit(umi, { units: 1400000 }) - ); + const withCU = baseTransaction + .useV1() + .setTransactionConfig({ computeUnitLimit: 1_400_000 }); // Step 8: Calculate optimal compute unit limit console.log("Estimating required compute units..."); const requiredUnits = await getRequiredCU(umi, withCU.build(umi)); // Step 9: Build the final optimized transaction - const finalTransaction = baseTransaction.prepend( - setComputeUnitPrice(umi, { microLamports: priorityFee }) - ).prepend( - setComputeUnitLimit(umi, { units: requiredUnits }) + const totalPriorityFeeLamports = Math.ceil( + (priorityFee * requiredUnits) / 1_000_000 ); - console.log(`Transaction optimized with Priority Fee: ${priorityFee} microLamports and ${requiredUnits} compute units`); + const finalTransaction = baseTransaction + .useV1() + .setTransactionConfig({ + computeUnitLimit: requiredUnits, + priorityFee: lamports(totalPriorityFeeLamports), + }); + console.log(`Transaction optimized with a total priority fee of ${totalPriorityFeeLamports} lamports and ${requiredUnits} compute units`); // Step 10: Send and confirm the transaction console.log("Sending optimized transaction..."); @@ -369,3 +411,10 @@ example().catch(console.error); ``` {% /totem-accordion %} {% /totem %} + +## Notes + +- This guide targets Umi 1.6.0 or later and V1 transactions. +- `TransactionV1Config.priorityFee` is a total lamport amount, while `getRecentPrioritizationFees` returns a price in micro-lamports per compute unit. +- V1 transactions do not support Address Lookup Tables or Compute Budget instructions. +- See [Migrating from V0 to V1 Transactions](/dev-tools/umi/guides/migrate-to-transaction-v1) when converting an existing V0 transaction builder. diff --git a/src/pages/en/dev-tools/umi/guides/serializing-and-deserializing-transactions.md b/src/pages/en/dev-tools/umi/guides/serializing-and-deserializing-transactions.md index 0b29fc5f7..e8de9dbf9 100644 --- a/src/pages/en/dev-tools/umi/guides/serializing-and-deserializing-transactions.md +++ b/src/pages/en/dev-tools/umi/guides/serializing-and-deserializing-transactions.md @@ -3,7 +3,7 @@ title: Serializing, Deserializing, and sending Transactions metaTitle: Umi - Serializing, Deserializing, and sending Transactions description: Learn how to Serialize and Deserialize Transactions to move them across different environments while using the Metaplex Umi client. created: '08-15-2024' -updated: '08-15-2024' +updated: '09-21-2026' --- **In this guide we're going to talk about:** @@ -121,13 +121,17 @@ const umi = createUmi('https://api.devnet.solana.com') {% /totem %} +{% callout type="note" %} +The examples use V1 transactions and require Umi 1.6.0 or later and `@solana/web3.js` 1.99.0 or later. When a wallet signs the deserialized transaction, that wallet must also support transaction version `1`. +{% /callout %} + ## Serialization Serialization of a transaction is the process of converting the transaction object into a series of bytes or string that saves the state of the transaction in an easily transmittable form. This allows it to be passed through the likes of a http request. Within the serialization example we're going to: - Use the `NoopSigner` to add the `Payer` as `Signer` in the instruction -- Create a Versioned Transaction and sign it with the `collectionAuthority` and the `Asset` +- Create a V1 transaction and sign it with the `collectionAuthority` and the `Asset` - Serialize it so all the details are preserved and can be accurately reconstructed by the frontend - And send it as a String, instead of a u8, so it can be passed through a request @@ -191,7 +195,7 @@ const createAssetTx = await create(umi, { name: 'My NFT', uri: 'https://example.com/my-nft.json', }) - .useV0() + .useV1() .setBlockhash(await umi.rpc.getLatestBlockhash()) .buildAndSign(umi); @@ -283,7 +287,7 @@ const frontEndSigner = generateSigner(umi); name: 'My NFT', uri: 'https://example.com/my-nft.json', }) - .useV0() + .useV1() .setBlockhash(await umi.rpc.getLatestBlockhash()) .buildAndSign(umi); diff --git a/src/pages/en/dev-tools/umi/toolbox/address-lookup-table.md b/src/pages/en/dev-tools/umi/toolbox/address-lookup-table.md index fc2918647..cb11a7eff 100644 --- a/src/pages/en/dev-tools/umi/toolbox/address-lookup-table.md +++ b/src/pages/en/dev-tools/umi/toolbox/address-lookup-table.md @@ -6,6 +6,10 @@ description: How to use Address Lookup Tables with Umi. The SPL Address Lookup Table program can be used to reduce the size of transactions by creating custom lookup tables — a.k.a **LUTs** or **ALTs** — before using them in transactions. This program allows you to create and extend LUTs. You can learn more about this program in [Solana's official documentation](https://docs.solana.com/developing/lookup-tables). +{% callout type="warning" %} +Address Lookup Tables are only supported by V0 transactions. A transaction builder that uses `setAddressLookupTables()` must use `useV0()`, even when Umi is configured to use V1 by default. +{% /callout %} + ## Create empty LUTs This instruction allows you to create an empty Address Lookup Table (LUT) account. @@ -75,8 +79,11 @@ for (const createLutBuilder of createLutBuilders) { await createLutBuilder.sendAndConfirm(umi) } -// 3. Use the LUTs in the base transaction builder. -await baseBuilder.setAddressLookupTables(lutAccounts).sendAndConfirm(umi) +// 3. Use the LUTs in a V0 transaction. +await baseBuilder + .useV0() + .setAddressLookupTables(lutAccounts) + .sendAndConfirm(umi) ``` ## Freeze a LUT diff --git a/src/pages/en/dev-tools/umi/toolbox/priority-fees-and-compute-managment.md b/src/pages/en/dev-tools/umi/toolbox/priority-fees-and-compute-managment.md index 384acb4cb..ed5a904fe 100644 --- a/src/pages/en/dev-tools/umi/toolbox/priority-fees-and-compute-managment.md +++ b/src/pages/en/dev-tools/umi/toolbox/priority-fees-and-compute-managment.md @@ -1,39 +1,81 @@ --- title: Priority Fees and Compute Management metaTitle: Priority Fees and Compute Management | Toolbox -description: How to use Priority Fees and the Compute Budget Program with Umi. +description: Configure compute unit limits and priority fees for Umi V1 and V0 transactions. +keywords: + - Umi priority fees + - Umi compute units + - TransactionV1Config + - Compute Budget Program +about: + - Umi + - Solana Transaction Fees +proficiencyLevel: Intermediate +programmingLanguage: + - JavaScript + - TypeScript +created: '09-04-2024' +updated: '09-21-2026' --- -The Compute Budget Program allows us to set a custom Compute Unit limit and price. You can read more about this program in [Solana's official documentation](https://docs.solana.com/developing/programming-model/runtime#compute-budget). +## Summary -## Set Compute Unit limit +Use `setTransactionConfig()` to configure compute units and priority fees on V1 transactions. -This instruction allows you to set a custom Compute Unit limit for your transaction. +- V1 uses `computeUnitLimit` and a total `priorityFee`. +- Umi V1 transaction builders reject Compute Budget program instructions. +- V0 uses `setComputeUnitLimit` and `setComputeUnitPrice`. +- Priority fee estimates expressed in micro-lamports per compute unit must be converted to total lamports for V1. -```ts -import { transactionBuilder } from '@metaplex-foundation/umi' -import { setComputeUnitLimit } from '@metaplex-foundation/mpl-toolbox' +Umi V1 transactions store compute limits and the total priority fee in the transaction message, while V0 transactions use Compute Budget program instructions. + +## Configure V1 Compute Units and Priority Fees + +V1 transactions configure their compute unit limit and total priority fee with `setTransactionConfig()`. + +```ts {% title="V1 compute configuration" %} +import { lamports, transactionBuilder } from '@metaplex-foundation/umi' await transactionBuilder() - .add(setComputeUnitLimit(umi, { units: 600_000 })) // Set the Compute Unit limit. - .add(...) // Any instruction(s) here. + .add(myInstruction) + .useV1() + .setTransactionConfig({ + computeUnitLimit: 600_000, + priorityFee: lamports(600), + }) .sendAndConfirm(umi) ``` -## Set Compute Unit price / Priority Fees +The `priorityFee` is the total fee, not the price per compute unit. For a price of 1,000 micro-lamports and a limit of 600,000 units, the total is `600,000 × 1,000 ÷ 1,000,000 = 600` lamports. + +{% callout type="warning" %} +Do not add `setComputeUnitLimit` or `setComputeUnitPrice` instructions to a V1 transaction builder. Umi rejects Compute Budget instructions in V1 transactions. +{% /callout %} + +## Configure V0 Compute Units and Priority Fees -This instruction allows you to set a custom price per Compute Unit for your transaction +V0 transactions continue to use Compute Budget program instructions from `@metaplex-foundation/mpl-toolbox`. -```ts +```ts {% title="V0 compute configuration" %} import { transactionBuilder } from '@metaplex-foundation/umi' -import { setComputeUnitPrice } from '@metaplex-foundation/mpl-toolbox' +import { + setComputeUnitLimit, + setComputeUnitPrice, +} from '@metaplex-foundation/mpl-toolbox' await transactionBuilder() - .add(setComputeUnitPrice(umi, { microLamports: 1 })) // Set the price per Compute Unit in micro-lamports. - .add(...) // Any instruction(s) here. + .add(setComputeUnitLimit(umi, { units: 600_000 })) + .add(setComputeUnitPrice(umi, { microLamports: 1_000 })) + .add(myInstruction) + .useV0() .sendAndConfirm(umi) ``` -{% callout title="Guide how to calculate units and microLamports" type="note" %} -To be able to choose proper numbers for `microLamports` and `units` there was a [small guide](/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees) created that walks through different RPC calls that can be used for calculation. -{% /callout %} +Use V0 when the transaction requires an [Address Lookup Table](/dev-tools/umi/toolbox/address-lookup-table) or the connected wallet does not support V1 transactions. + +## Notes + +- Umi 1.6.0 or later is required for `useV1()` and `setTransactionConfig()`. +- The V1 compute unit limit cannot exceed 1,400,000. +- See [Optimal Transaction Landing](/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees) to estimate compute units and fees. +- See [Migrating from V0 to V1 Transactions](/dev-tools/umi/guides/migrate-to-transaction-v1) for all compatibility requirements. diff --git a/src/pages/en/dev-tools/umi/transactions.md b/src/pages/en/dev-tools/umi/transactions.md index e5cbd3138..293e4dff4 100644 --- a/src/pages/en/dev-tools/umi/transactions.md +++ b/src/pages/en/dev-tools/umi/transactions.md @@ -2,7 +2,30 @@ title: Sending transactions metaTitle: Sending transactions | Umi description: Sending transactions using Metaplex Umi and Transaction Builders +keywords: + - Umi transactions + - Solana transaction v1 + - transaction builder + - sendAndConfirm +about: + - Umi + - Solana Transactions +proficiencyLevel: Intermediate +programmingLanguage: + - JavaScript + - TypeScript +created: '01-16-2024' +updated: '09-21-2026' --- +## Summary + +Umi creates, signs, sends, and confirms Solana transactions through transaction factories, immutable transaction builders, and its RPC interface. + +- Use `useV1()` to select V1 on a transaction builder. +- Use `setTransactionConfig()` instead of Compute Budget instructions with V1. +- Umi 1.6.0 still defaults to V0 unless configured otherwise. +- Keep transactions that require Address Lookup Tables on V0. + Managing and sending transactions is an important part of any Solana client. To help manage them, Umi provides a bunch of components: - A [TransactionFactoryInterface](https://umi.typedoc.metaplex.com/interfaces/umi.TransactionFactoryInterface.html) that can be used to create and (de)serialize transactions. @@ -17,19 +40,26 @@ Umi defines its own set of interfaces for transactions, instructions and all oth - [TransactionMessage](https://umi.typedoc.metaplex.com/interfaces/umi.TransactionMessage.html): A transaction message is composed of all required public keys, one or many compiled instructions using indexes instead of public keys, a recent blockhash and other attributes such as its version. A transaction message can have one of the following versions: - Version: "legacy": The first Solana iteration of the transaction message. - Version: 0: The first transaction message version that introduces transaction versioning. It also introduces address lookup tables. + - Version: 1: A transaction format with a 4,096-byte limit and compute configuration stored in the message. It does not support Address Lookup Tables. - [Instruction](https://umi.typedoc.metaplex.com/types/umi.Instruction.html): An instruction is composed of a program id, a list of [AccountMeta](https://umi.typedoc.metaplex.com/types/umi.AccountMeta.html) and some serialized data. Each account `AccountMeta` is composed of a public key, a boolean indicating whether it will be signing the transaction and another boolean indicating whether it's writable or not. -To create a new transaction, you may use the `create` method of the `TransactionFactoryInterface`. For instance, here's how you'd create a version `0` transaction with a single instruction: +To create a new transaction, you may use the `create` method of the `TransactionFactoryInterface`. The following example creates a version `1` transaction with a single instruction: -```ts +```ts {% title="Create a V1 transaction" %} const transaction = umi.transactions.create({ - version: 0, + version: 1, blockhash: (await umi.rpc.getLatestBlockhash()).blockhash, instructions: [myInstruction], payer: umi.payer.publicKey, + transactionConfig: { + computeUnitLimit: 200_000, + loadedAccountsDataSizeLimit: 64 * 1024 * 1024, + }, }) ``` +The low-level `create()` method does not apply transaction builder defaults, so V1 callers must provide nonzero compute and loaded-account data limits. + The transaction factory interface can also be used to serialize and deserialize transactions and their messages. ```ts @@ -89,7 +119,9 @@ And there's much more you can do with transaction builders. Feel free to [read t // Setters. builder = builder.setVersion(myTransactionVersion) // Sets the transaction version. builder = builder.useLegacyVersion() // Sets the transaction version to "legacy". -builder = builder.useV0() // Sets the transaction version to 0 (default). +builder = builder.useV0() // Sets the transaction version to 0. +builder = builder.useV1() // Sets the transaction version to 1. +builder = builder.setTransactionConfig(myV1Config) // Sets compute limits and fees for version 1. builder = builder.empty() // Removes all instructions from the builder but keeps the configurations. builder = builder.setItems(myWrappedInstructions) // Overwrite the wrapped instructions with the given ones. builder = builder.setAddressLookupTables(myLuts) // Set the address lookup tables, only for version 0 transactions. @@ -190,9 +222,39 @@ Or use `sendAndConfirm()` to wait for the transaction finalization for you. To d const confirmResult = await builder.sendAndConfirm(umi, {confirm: {commitment: 'finalized'}}) ``` +## Using V1 Transactions + +V1 transaction builders use `useV1()` and store compute configuration in the transaction message. + +```ts {% title="Send a V1 transaction" %} +import { lamports, transactionBuilder } from '@metaplex-foundation/umi' +import { transferSol } from '@metaplex-foundation/mpl-toolbox' + +await transactionBuilder() + .add(transferSol(umi, transferArgs)) + .useV1() + .setTransactionConfig({ + computeUnitLimit: 600_000, + priorityFee: lamports(600), + }) + .sendAndConfirm(umi) +``` + +Umi defaults to V0 for backward compatibility. Set V1 as the application default when all supported wallets can sign it: + +```ts {% title="Configure V1 as the default" %} +const umi = createUmi('https://api.mainnet-beta.solana.com', { + defaultTransactionVersion: 1, +}) +``` + +{% callout type="warning" %} +Umi transaction builders reject Compute Budget instructions when building V1 transactions; use `setTransactionConfig()` instead. Low-level `umi.transactions.create()` does not apply this builder check, but the Solana runtime ignores Compute Budget instructions for V1 configuration. Address Lookup Tables are not supported by V1. See [Migrating from V0 to V1 Transactions](/dev-tools/umi/guides/migrate-to-transaction-v1) for conversion steps and compatibility requirements. +{% /callout %} + ## Using address lookup tables -Starting from version 0 transactions, you may use address lookup tables to reduce the size of transactions. +Address Lookup Tables reduce the account-key footprint of V0 transactions but are not supported by V1. ```ts const myLut: AddressLookupTableInput = { @@ -271,3 +333,10 @@ This will return an instance of [`TransactionWithMeta`](https://umi.typedoc.meta const transaction = await umi.rpc.getTransaction(signature) const logs: string[] = transaction.meta.logs ``` + +## Notes + +- Umi 1.6.0 or later is required for V1 transactions. +- Umi's Web3.js-based packages require `@solana/web3.js` 1.99.0 or later for V1. +- Connected wallets must support transaction version `1`; Umi does not perform this compatibility check. +- Transactions that require Address Lookup Tables must remain on V0. diff --git a/src/pages/en/dev-tools/umi/web3js-differences-and-adapters.md b/src/pages/en/dev-tools/umi/web3js-differences-and-adapters.md index 194ebcb07..bc5ad3917 100644 --- a/src/pages/en/dev-tools/umi/web3js-differences-and-adapters.md +++ b/src/pages/en/dev-tools/umi/web3js-differences-and-adapters.md @@ -2,8 +2,30 @@ title: '@solana/web3.js Differences and Adapters' metaTitle: 'Umi - @solana/web3.js Differences and Adapters' description: 'Difference and Adapters to make Metaplex Umi work with Solana web3js.' +keywords: + - Umi web3.js adapters + - Solana transaction v1 + - web3.js conversion +about: + - Umi + - web3.js +proficiencyLevel: Intermediate +programmingLanguage: + - JavaScript + - TypeScript +created: '01-16-2024' +updated: '09-21-2026' --- +## Summary + +The Umi Web3.js adapters convert common Solana types between Umi and `@solana/web3.js`. + +- Install or import helpers from `@metaplex-foundation/umi-web3js-adapters`. +- Convert public keys, keypairs, instructions, transactions, and messages. +- Use Umi 1.6.0 and `@solana/web3.js` 1.99.0 or later for V1 transactions. +- Keep native Web3.js transaction creation on V0 because Web3.js 1.x cannot create V1 transactions by itself. + 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. @@ -207,13 +229,14 @@ 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 +The Solana runtime supports three transaction formats: +- Legacy transaction: The original transaction format +- V0 transaction: Adds support for Address Lookup Tables +- V1 transaction: Raises the transaction size limit to 4,096 bytes and stores compute configuration in the message -**Note**: if you're not familiar with the concept of Versioned Transactions, read more about it [in the Solana Versioned Transactions docs](https://solana.com/en/docs/advanced/versions) +**Note**: If you're not familiar with versioned transactions, read [Migrating from V0 to V1 Transactions](/dev-tools/umi/guides/migrate-to-transaction-v1). -For `umi` and `umi-web3js-adapters` we added support for both transaction types! +Umi 1.6.0 and `umi-web3js-adapters` support legacy, V0, and V1 transactions. V1 requires `@solana/web3.js` 1.99.0 or later. ### Umi ```ts @@ -225,8 +248,8 @@ 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) +// Create a new Umi V1 transaction +const umiVersionedTransaction = transferSol(umi, {...TransferParams}).useV1().build(umi) ``` ### Web3Js @@ -268,10 +291,10 @@ const umiTransaction = transferSol(umi, {...TransferParams}).useLegacyVersion(); // Convert it using the UmiWeb3jsAdapters Package const web3jsTransaction = toWeb3JsTransaction(umiTransaction); -/// Versioned Transactions /// +/// V1 transactions /// -// Create a new Versioned Transaction -const umiVersionedTransaction = transferSol(umi, {...TransferParams}).useV0().build(umi) +// Create a new V1 transaction +const umiVersionedTransaction = transferSol(umi, {...TransferParams}).useV1().build(umi) // Convert it using the UmiWeb3jsAdapters Package const web3jsVersionedTransaction = toWeb3JsTransaction(umiVersionedTransaction); @@ -315,10 +338,14 @@ const blockhash = await umi.rpc.getLatestBlockhash() const instructions = transfer(umi, {...TransferParams}).getInstructions() const umiVersionedTransaction = umi.transactions.create({ - version: 0, + version: 1, payer: frontEndSigner.publicKey, instructions, blockhash: blockhash.blockhash, + transactionConfig: { + computeUnitLimit: 200_000, + loadedAccountsDataSizeLimit: 64 * 1024 * 1024, + }, }); const umiMessage = umiVersionedTransaction.message @@ -370,3 +397,11 @@ const Web3JsMessage = new TransactionMessage({...createMessageParams}).compileTo // Convert it using the UmiWeb3jsAdapters Package const umiMessage = fromWeb3JMessage(Web3JsMessage); ``` + +## Notes + +Web3.js 1.x has limited support for V1 transactions. + +- Web3.js 1.x can deserialize V1 transactions but cannot create or serialize them on its own. +- Umi provides the V1 serializer used by the adapters. +- The native Web3.js transaction creation examples remain on V0. diff --git a/src/pages/en/solana/solana-transaction-fundamentals.md b/src/pages/en/solana/solana-transaction-fundamentals.md index 47d855b2b..f7af7defe 100644 --- a/src/pages/en/solana/solana-transaction-fundamentals.md +++ b/src/pages/en/solana/solana-transaction-fundamentals.md @@ -4,7 +4,7 @@ metaTitle: Solana Transaction Fundamentals | How Transactions Work description: Learn how Solana transactions work, including structure, signing, sending, and confirmation. Essential knowledge for building reliable applications. # remember to update dates also in /components/products/guides/index.js created: '02-04-2026' -updated: null +updated: '09-21-2026' --- A comprehensive guide to understanding how Solana transactions work from structure to confirmation. {% .lead %} @@ -185,22 +185,36 @@ const result = await myBuilder.sendAndConfirm(umi, { ## Versioned Transactions -Solana currently supports two transaction formats: +Solana supports three transaction formats: ### Legacy Transactions + +Legacy transactions use Solana's original transaction format without Address Lookup Tables. + - Original format - Limited to 35 accounts - Simpler structure -### Versioned Transactions (v0) +### V0 Transactions + +V0 transactions add Address Lookup Table support for transactions that need more accounts. + - Support **Address Lookup Tables** (ALTs) - Can reference up to 256 accounts - Required for complex DeFi operations +### V1 Transactions + +V1 transactions increase the transaction size limit and store compute configuration in the message. + +- Support transactions up to 4,096 bytes +- Store compute budget configuration in the transaction message +- Do not support Address Lookup Tables + ```javascript -// UMI uses V0 transactions by default +// Umi uses V0 transactions by default. Opt in to V1 explicitly. const result = await myBuilder - .useV0() // Explicit, but this is already the default + .useV1() .sendAndConfirm(umi) // To use legacy transactions instead @@ -217,17 +231,19 @@ const [lutBuilder, lut] = createLut(umi, { }) await lutBuilder.sendAndConfirm(umi) -// Use the lookup table in your transaction -await myBuilder.setAddressLookupTables([lut]).sendAndConfirm(umi) +// Address Lookup Tables require V0. +await myBuilder + .useV0() + .setAddressLookupTables([lut]) + .sendAndConfirm(umi) ``` -{% callout title="When to Use Versioned Transactions" %} -Use versioned transactions when: -- Your transaction involves many accounts (>35) -- You're interacting with DeFi protocols that require ALTs -- You want to reduce transaction size +{% callout title="Choosing a Transaction Version" %} +- Use V1 for transactions larger than 1,232 bytes when the wallet supports transaction version `1`. +- Use V0 when the transaction requires an Address Lookup Table. +- Use legacy transactions only when compatibility requires the original format. -For simple operations (transfers, basic mints), legacy transactions work fine. +Umi defaults to V0 for backward compatibility. See [Migrating from V0 to V1 Transactions](/dev-tools/umi/guides/migrate-to-transaction-v1) before changing the application-wide default. {% /callout %} ## Transaction Size Limits @@ -236,17 +252,19 @@ Solana transactions have strict size limits: | Limit | Value | |-------|-------| -| Maximum transaction size | 1232 bytes | -| Maximum accounts | 35 (legacy) / 256 (versioned with ALTs) | +| Legacy and V0 transaction size | 1,232 bytes | +| V1 transaction size | 4,096 bytes | +| Address Lookup Tables | V0 only | | Maximum instructions | Limited by size | ### Dealing with Size Limits If your transaction is too large: -1. **Use Address Lookup Tables** - Compress account references -2. **Split into multiple transactions** - Execute sequentially -3. **Optimize instruction data** - Minimize serialized data +1. **Use V1** - Increase the size limit to 4,096 bytes when no Address Lookup Table is required +2. **Use Address Lookup Tables with V0** - Compress account references +3. **Split into multiple transactions** - Execute sequentially +4. **Optimize instruction data** - Minimize serialized data ## Simulation diff --git a/src/pages/ja/dev-tools/umi/guides/migrate-to-transaction-v1.md b/src/pages/ja/dev-tools/umi/guides/migrate-to-transaction-v1.md new file mode 100644 index 000000000..9e83c7f84 --- /dev/null +++ b/src/pages/ja/dev-tools/umi/guides/migrate-to-transaction-v1.md @@ -0,0 +1,268 @@ +--- +title: V0からV1トランザクションへの移行 +metaTitle: V0からV1トランザクションへの移行 | Umi +description: コンピュートバジェット、優先料金、ウォレット互換性を含め、Umiのトランザクションビルダーと直接作成するトランザクションをSolana V0トランザクションからV1トランザクションへ移行します。 +keywords: + - Umi transaction v1 + - Solana transaction v1 + - Umi v0 migration + - TransactionV1Config + - useV1 + - setTransactionConfig + - SIMD-0385 +about: + - Umi + - Solana Transaction V1 + - Transaction Migration +proficiencyLevel: Intermediate +programmingLanguage: + - JavaScript + - TypeScript +created: '09-21-2026' +updated: '09-21-2026' +howToSteps: + - Umiパッケージをバージョン1.6.0以降、web3.jsをバージョン1.99.0以降にアップグレードする + - トランザクションビルダーごと、またはアプリケーションのデフォルトとしてV1を選択する + - Compute Budget命令をTransactionV1Configに置き換える + - Address Lookup Tablesを必要とするトランザクションはV0のままにする + - 署名前に、接続されるすべてのウォレットがV1トランザクションをサポートしていることを確認する +howToTools: + - Umi 1.6.0 or later + - web3.js 1.99.0 or later + - Solana RPC +faqs: + - q: UmiはデフォルトでV1トランザクションを使用しますか? + a: いいえ。Umi 1.6.0では、後方互換性のためV0がデフォルトのままです。トランザクションビルダーでuseV1を呼び出すか、Umiの作成時にdefaultTransactionVersionを1に設定してください。 + - q: UmiのV1トランザクションでAddress Lookup Tableを使用できますか? + a: いいえ。V1トランザクションはAddress Lookup Tablesをサポートしません。Address Lookup Tableを必要とするトランザクションはV0のままにしてください。 + - q: V1トランザクションにCompute Budgetプログラム命令を含めることはできますか? + a: いいえ。UmiはCompute Budget命令を含むV1トランザクションビルダーを拒否します。コンピュートユニット制限、優先料金の合計、ロード済みアカウントデータサイズ制限、またはヒープサイズの設定にはsetTransactionConfigを使用してください。 + - q: V1トランザクションの優先料金はコンピュートユニットあたりの価格ですか? + a: いいえ。TransactionV1Config.priorityFeeはSolAmountとして指定する優先料金の合計です。マイクロラムポート単位の価格にコンピュートユニット制限を掛け、1,000,000で割り、ラムポート単位に切り上げて変換します。 + - q: すべてのSolanaウォレットがV1トランザクションをサポートしていますか? + a: いいえ。Umiはウォレットアダプター向けにV1トランザクションをシリアライズできますが、接続されたウォレットがトランザクションバージョン1を受け入れて署名できる必要があります。V1をアプリケーション全体のデフォルトにする前に、ウォレットの対応状況を確認してください。 +--- + +UmiアプリケーションをV0から[V1トランザクション](https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0385-transaction-v1.md)へ移行すると、より大きなトランザクションを使用し、トランザクションメッセージ上でコンピュートバジェットを直接設定できます。 {% .lead %} + +{% callout title="移行する内容" %} +このガイドでは、UmiのV0トランザクションビルダーをV1へ移行し、Compute Budget命令を`TransactionV1Config`に置き換え、V1をグローバルに設定し、V0のままにする必要があるトランザクションを特定します。 +{% /callout %} + +## まとめ + +Umi 1.6.0では、`useV1()`、`defaultTransactionVersion: 1`、およびトランザクションを直接作成する際の`version: 1`を通じて、オプトインでV1トランザクションをサポートします。 + +- V1では、シリアライズ後のトランザクション上限が1,232バイトから4,096バイトに増えます。 +- V1では、コンピュート制限と優先料金の合計を`TransactionV1Config`に格納します。 +- V1はAddress Lookup TablesとCompute Budget命令をサポートしません。 +- Umiのデフォルトは引き続きV0であり、接続されるウォレットがV1に対応している必要があります。 + +## クイックスタート + +トランザクションビルダーでV1を選択し、Compute Budget命令を`setTransactionConfig`に置き換えます。 + +1. Umiを1.6.0以降、`@solana/web3.js`を1.99.0以降にアップグレードします。 +2. トランザクションビルダーに`.useV1()`を追加します。 +3. `setComputeUnitLimit`命令と`setComputeUnitPrice`命令を削除します。 +4. `.setTransactionConfig({ computeUnitLimit, priorityFee })`を追加します。 +5. アプリケーションがサポートするすべてのウォレットでV1の署名をテストします。 + +**ジャンプ:** [前提条件](#前提条件) · [V0とV1の違い](#v0とv1トランザクションの違い) · [ビルダーの移行](#トランザクションビルダーをv1へ移行する) · [アプリケーションのデフォルト](#v1をアプリケーションのデフォルトに設定する) · [直接作成](#トランザクションの直接作成をv1へ移行する) · [Address Lookup Tables](#address-lookup-tableを使用するトランザクションをv0のままにする) · [一般的なエラー](#v1移行でよくあるエラー) · [FAQ](#faq) + +## 前提条件 + +V1への移行には、互換性のあるUmi、Web3.js、RPC、ウォレットの各バージョンが必要です。 + +| コンポーネント | 要件 | +|-----------|-------------| +| Umi packages | 1.6.0以降 | +| `@solana/web3.js` | 1.99.0以降 | +| Solana clusters | mainnet-beta、devnet、testnetでV1が有効 | +| Wallet | トランザクションバージョン`1`を受け入れて署名できること | + +{% callout type="warning" %} +接続されるすべてのウォレット経路がトランザクションバージョン`1`に対応するまで、V1をグローバルに有効化しないでください。Umiはウォレットアダプター向けにトランザクションをシリアライズしますが、互換性のないウォレットに署名させることはできません。 +{% /callout %} + +## V0とV1トランザクションの違い + +V1ではトランザクションのサイズ上限が増えますが、V0のAddress Lookup TablesやCompute Budget命令はサポートされません。 + +| 機能 | V0 | V1 | +|------------|----------------|----------------| +| シリアライズ後のサイズ上限 | 1,232バイト | 4,096バイト | +| Address lookup tables | サポートあり | サポートなし | +| コンピュートユニット制限 | Compute Budget命令 | `transactionConfig.computeUnitLimit` | +| 優先料金 | コンピュートユニットあたりのマイクロラムポート | `transactionConfig.priorityFee`内の合計`SolAmount` | +| Umi 1.6.0でのデフォルト | はい | いいえ、オプトインが必要 | +| ビルダーのセレクター | `useV0()` | `useV1()` | + +V1は、Address Lookup Tableに依存せず、トランザクションがV0のサイズ上限を超える場合に最も有用です。 + +## トランザクションビルダーをV1へ移行する + +V0トランザクションビルダーは、Compute Budget命令を`useV1()`と`setTransactionConfig()`に置き換えることでV1へ移行できます。 + +### 移行前のV0トランザクションビルダー + +V0トランザクションビルダーでは、コンピュートユニット制限と価格を命令として指定します。 + +```typescript {% title="transaction-v0.ts" %} +import { transactionBuilder } from '@metaplex-foundation/umi' +import { + setComputeUnitLimit, + setComputeUnitPrice, + transferSol, +} from '@metaplex-foundation/mpl-toolbox' + +await transactionBuilder() + .add(setComputeUnitLimit(umi, { units: 600_000 })) + .add(setComputeUnitPrice(umi, { microLamports: 1_000 })) + .add(transferSol(umi, transferArgs)) + .sendAndConfirm(umi) +``` + +### 移行後のV1トランザクションビルダー + +V1トランザクションビルダーでは、コンピュートユニット制限と優先料金の合計をトランザクションメッセージ内に指定します。 + +```typescript {% title="transaction-v1.ts" %} +import { lamports, transactionBuilder } from '@metaplex-foundation/umi' +import { transferSol } from '@metaplex-foundation/mpl-toolbox' + +await transactionBuilder() + .add(transferSol(umi, transferArgs)) + .useV1() + .setTransactionConfig({ + computeUnitLimit: 600_000, + priorityFee: lamports(600), + }) + .sendAndConfirm(umi) +``` + +合計料金の`600`ラムポートは、`600,000 × 1,000 ÷ 1,000,000`に相当します。変換結果が整数のラムポートにならない場合は切り上げてください。 + +{% callout type="note" %} +`setTransactionConfig()`は設定全体を置き換えます。個々のフィールドを指定して繰り返し呼び出すのではなく、カスタムV1設定をすべて同じ呼び出しに含めてください。 +{% /callout %} + +## V1をアプリケーションのデフォルトに設定する + +`defaultTransactionVersion: 1`を設定すると、ビルダーが別のバージョンを明示的に選択しない限り、すべてのトランザクションビルダーがV1を使用します。 + +```typescript {% title="umi.ts" %} +import { createUmi } from '@metaplex-foundation/umi-bundle-defaults' + +const umi = createUmi('https://api.mainnet-beta.solana.com', { + defaultTransactionVersion: 1, +}) +``` + +このオプションは、Metaplexのプログラムライブラリが返すビルダーにも適用されます。`useV0()`を呼び出すビルダーは、引き続きアプリケーションのデフォルトを上書きします。 + +トランザクションファクトリーを直接インストールするアプリケーションでは、代わりにプラグインを設定できます。 + +```typescript {% title="umi-with-custom-plugins.ts" %} +import { web3JsTransactionFactory } from '@metaplex-foundation/umi-transaction-factory-web3js' + +umi.use(web3JsTransactionFactory({ defaultTransactionVersion: 1 })) +``` + +## トランザクションの直接作成をV1へ移行する + +`umi.transactions.create()`を直接呼び出す場合は、`version: 1`を設定し、ゼロではないランタイム制限を明示的に指定する必要があります。 + +```typescript {% title="create-transaction-v1.ts" %} +const transaction = umi.transactions.create({ + version: 1, + blockhash: (await umi.rpc.getLatestBlockhash()).blockhash, + instructions: [myInstruction], + payer: umi.payer.publicKey, + transactionConfig: { + computeUnitLimit: 200_000, + loadedAccountsDataSizeLimit: 64 * 1024 * 1024, + }, +}) +``` + +`TransactionBuilder`は、コンピュート制限とロード済みアカウント制限が省略された場合に、従来と同等のデフォルト値を補います。低レベルの`create()`メソッドは補わないため、省略された制限はランタイムによってゼロとして扱われます。 + +## V1トランザクションの制限を設定する + +`TransactionV1Config`は、コンピュート、アカウントデータ、ヒープサイズ、優先料金の合計を制御します。 + +| フィールド | 意味 | 有効範囲または動作 | +|-------|---------|-------------------------| +| `computeUnitLimit` | コンピュートユニットの最大値 | `0`から`1,400,000`までの整数 | +| `priorityFee` | 優先料金の合計 | 通常は`lamports(...)`で作成する`SolAmount` | +| `loadedAccountsDataSizeLimit` | ロード済みアカウントデータの最大値 | 最大64 MiB | +| `heapSize` | プログラムのヒープフレームサイズ | 32,768から262,144バイトまで(1,024バイト単位) | + +これらのフィールドを省略すると、ビルダーは`computeUnitLimit`のデフォルトを`min(200,000 × 命令数, 1,400,000)`、`loadedAccountsDataSizeLimit`のデフォルトを64 MiBに設定します。 + +## Address Lookup Tableを使用するトランザクションをV0のままにする + +[Address Lookup Tables](/dev-tools/umi/toolbox/address-lookup-table)を必要とするトランザクションは、V0のままにする必要があります。 + +```typescript {% title="transaction-v0-with-lookup-table.ts" %} +const builder = transactionBuilder() + .add(myInstruction) + .useV0() + .setAddressLookupTables([myLookupTable]) +``` + +トランザクションをV1へ強制的に移行するためだけにAddress Lookup Tableを削除しないでください。コンパイル後のアカウントリストとシリアライズ後のサイズを比較し、トランザクションの要件を満たす形式を使用してください。 + +## カスタムUmi連携を更新する + +Umi 1.6.0へアップグレードする際、カスタムトランザクションファクトリーとバージョンを網羅的に処理するコードにはV1サポートを追加する必要があります。 + +- カスタム`TransactionFactoryInterface`実装に`getDefaultVersion()`を実装します。 +- `TransactionVersion`を網羅的に分岐するコードに`1`のケースを追加します。 +- V0のバージョンフィールドが必須になったため、直接作成するV0の`TransactionInput`オブジェクトに`version: 0`を追加します。 +- トランザクションを読み取る際は`transaction.message.version`を確認します。V1メッセージには`transactionConfig`が含まれます。 + +UmiのRPC連携は`maxSupportedTransactionVersion: 1`を要求するため、`umi.rpc.getTransaction()`でV1トランザクションを取得できます。 + +## V1移行でよくあるエラー + +Umiは、互換性のないビルダーの組み合わせをトランザクション送信前に拒否します。 + +| エラー | 原因 | 修正方法 | +|-------|-------|-----| +| `V1 transactions ignore ComputeBudget instructions. Set the compute budget with setTransactionConfig instead.` | V1トランザクションビルダーに`setComputeUnitLimit`、`setComputeUnitPrice`、または別のCompute Budget命令が含まれている | 命令を削除し、`setTransactionConfig()`を使用する | +| `Address lookup tables are not supported by V1 transactions.` | V1トランザクションビルダーに1つ以上のAddress Lookup Tablesが設定されている | ビルダーをV0のままにするか、lookup tableの要件をなくす | +| `Transaction configs are only supported by V1 transactions.` | legacyまたはV0のトランザクションビルダーが`setTransactionConfig()`を呼び出している | `useV1()`を呼び出すか、V0でCompute Budget命令を使用する | +| ウォレットがトランザクションを拒否する、またはデシリアライズできない | ウォレットがトランザクションバージョン`1`をサポートしていない | ウォレットがV1をサポートするまで、そのウォレットのフローをV0のままにする | +| 直接作成したトランザクションがコンピュートバジェット不足で失敗する | `create()`に`computeUnitLimit`が指定されていない | ゼロではない`transactionConfig.computeUnitLimit`を設定する | + +## 注意事項 + +- Umi 1.6.0ではV1はオプトインであり、後方互換性のためデフォルトはV0のままです。 +- V1は2026年9月15日のepoch 1035にSolana mainnet-betaで有効化されました。 +- 送信とシミュレーションにはbase64エンコーディングが使用され、1,232バイトを超えるV1トランザクションに対応します。 +- Umiはシリアライズ前にコンピュートユニット制限とヒープサイズを検証します。 +- 実装と互換性の詳細は[metaplex-foundation/umi#216](https://github.com/metaplex-foundation/umi/pull/216)に記載されています。 + +## FAQ + +### UmiはデフォルトでV1トランザクションを使用しますか? + +Umi 1.6.0では、後方互換性のためV0がデフォルトのままです。トランザクションビルダーで`useV1()`を呼び出すか、Umiの作成時に`defaultTransactionVersion: 1`を設定してください。 + +### UmiのV1トランザクションでAddress Lookup Tableを使用できますか? + +V1トランザクションはAddress Lookup Tablesをサポートしません。Address Lookup Tableを必要とするトランザクションはV0のままにしてください。 + +### V1トランザクションにCompute Budgetプログラム命令を含めることはできますか? + +UmiはCompute Budget命令を含むV1トランザクションビルダーを拒否します。コンピュートユニット制限、優先料金の合計、ロード済みアカウントデータサイズ制限、またはヒープサイズの設定には`setTransactionConfig()`を使用してください。 + +### V1トランザクションの優先料金はコンピュートユニットあたりの価格ですか? + +`TransactionV1Config.priorityFee`はコンピュートユニットあたりの価格ではなく、`SolAmount`として指定する優先料金の合計です。マイクロラムポート単位の価格にコンピュートユニット制限を掛け、1,000,000で割り、ラムポート単位に切り上げて変換します。 + +### すべてのSolanaウォレットがV1トランザクションをサポートしていますか? + +トランザクションバージョン`1`への対応は、すべてのウォレットで共通ではありません。Umiはウォレットアダプター向けにV1トランザクションをシリアライズできますが、接続されたウォレットがトランザクションを受け入れて署名できる必要があります。 diff --git a/src/pages/ja/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees.md b/src/pages/ja/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees.md index a1961e81f..af85c8a3b 100644 --- a/src/pages/ja/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees.md +++ b/src/pages/ja/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees.md @@ -1,55 +1,86 @@ --- -title: コンピュートユニット(CU)と優先料金を使用した最適なトランザクション実行 -metaTitle: Umi - コンピュートユニット(CU)と優先料金を使用した最適なトランザクション実行 +title: コンピュートユニット(CU)と優先料金によるトランザクション実行の最適化 +metaTitle: Umi - コンピュートユニット(CU)と優先料金によるトランザクション実行の最適化 description: 適切なコンピュートユニット(CU)と優先料金を計算・設定して、Solanaトランザクションを最適化する方法を学びます。 +keywords: + - Umi transaction v1 + - compute units + - priority fees + - transaction optimization +about: + - Umi + - Solana Transaction V1 + - Priority Fees +proficiencyLevel: Intermediate +programmingLanguage: + - JavaScript + - TypeScript created: '12-02-2024' -updated: '12-02-2024' +updated: '09-21-2026' --- -Solanaでトランザクションを送信する際、2つの重要なパラメータを最適化することで、トランザクションの成功率とコスト効率を大幅に向上させることができます: +## まとめ + +UmiのV1トランザクションでは、シミュレーションでコンピュート消費量を推定し、コンピュート制限と優先料金の合計を`TransactionV1Config`に格納します。 + +- 1,400,000のコンピュートユニット制限でシミュレーションします。 +- 消費されたユニットに安全マージンを加えます。 +- コンピュートユニットあたりのマイクロラムポートで市場価格を見積もります。 +- `setTransactionConfig()`を呼び出す前に、見積もりをラムポート単位の合計料金へ変換します。 + +Solanaでトランザクションを送信する際は、2つの重要なパラメータを最適化することで、トランザクションの成功率とコスト効率を大幅に向上させることができます。 + +## クイックスタート + +トランザクションを送信する前に、V1のコンピュート制限と優先料金の合計を見積もります。 + +1. トランザクションの書き込み可能アカウントに対して最近支払われた料金から[優先料金を見積もります](#優先料金)。 +2. V1の最大コンピュート制限で[トランザクションをシミュレーションします](#コンピュートユニット制限)。 +3. `setTransactionConfig()`を使用して[見積もった値を適用します](#実装ガイド)。 +4. [SOL転送の完全な例を実行します](#sol転送の完全な例)。 ## 優先料金 -優先料金により、ローカル料金市場で入札を行い、トランザクションをより速く含めることができます。ネットワークが混雑し、複数のトランザクションが同じアカウントの変更を競合する場合、バリデータは優先料金の高いトランザクションを優先します。 +優先料金を使用すると、ローカル料金市場で入札し、トランザクションをより早く取り込ませることができます。ネットワークが混雑し、複数のトランザクションが同じアカウントの変更を競う場合、バリデーターは優先料金が高いトランザクションを優先します。 -優先料金に関する重要なポイント: -- 計算式:`compute_unit_limit * compute_unit_price` -- 料金が高いほど、より速い実行の可能性が向上 -- 現在のネットワーク競合に基づいて必要な分だけ支払う +優先料金の要点: +- 計算式は`compute_unit_limit * compute_unit_price`です +- 料金が高いほど、より早く取り込まれる可能性が高まります +- 現在のネットワーク競合に基づき、必要な金額だけを支払います ## コンピュートユニット制限 -コンピュートユニット(CU)は、トランザクションが必要とする計算リソースを表します。トランザクションは安全策として多くのCUをリクエストすることがデフォルトですが、これは多くの場合非効率です: +コンピュートユニット(CU)は、トランザクションに必要な計算リソースを表します。トランザクションは安全策として多くのCUを要求するのがデフォルトですが、多くの場合これは非効率です。 -1. 実際の使用量に関係なく、リクエストしたすべてのCUに対して優先料金を支払う -2. ブロックのCU容量は限られている - 過剰なCUのリクエストはブロック当たりの総トランザクション数を減らす +1. 実際の使用量に関係なく、要求したすべてのCUに対して優先料金を支払います +2. ブロックのCU容量は限られているため、過剰なCUの要求はブロックあたりの総トランザクション数を減らします -CU制限の最適化の利点: -- 必要なCUのみに支払うことによるトランザクションコストの削減 -- ブロック当たりのトランザクション数増加によるネットワーク効率の向上 -- 実行に十分なリソースを確保 +CU制限を最適化する利点: +- 必要なCUのみに支払うことでトランザクションコストを削減できます +- 1ブロックに含められるトランザクション数が増え、ネットワーク効率が向上します +- 実行に十分なリソースを確保できます -例えば、シンプルなトークン転送には20,000 CUしか必要ないかもしれませんが、NFTのミントには100,000 CUが必要な場合があります。これらの制限を適切に設定することで、コストと全体的なネットワークスループットの両方を最適化できます。 +たとえば、単純なトークン転送には20,000 CUで十分でも、NFTのミントには100,000 CUが必要な場合があります。これらの制限を適切に設定すると、コストとネットワーク全体のスループットの両方を最適化できます。 ## 実装ガイド -このガイドでは、推測ではなくプログラムで最適な値を計算する方法を説明します。 +このガイドでは、推測ではなくプログラムによって最適な値を計算する方法を説明します。 {% callout type="warning" %} -Umiはまだこれらのメソッドを実装していないため、コード例ではRPC呼び出しに`fetch`を使用しています。公式サポートが追加された際は、Umiの組み込みメソッドの使用を優先してください。 +Umiはまだこれらのメソッドを実装していないため、コード例ではRPC呼び出しに`fetch`を使用しています。公式サポートが追加されたら、Umiの組み込みメソッドを優先して使用してください。 {% /callout %} -### 優先料金の計算 -優先料金を使用する際は、競合を考慮に入れることが重要です。手動で巨大な数値を追加すると必要以上の料金を支払うことになり、数値が低すぎると競合が激しい場合にトランザクションがブロックに含まれない可能性があります。 +### 優先料金を計算する +優先料金を使用する際は、競合を考慮することが重要です。手動で非常に大きな値を指定すると必要以上の料金を支払う可能性があり、低すぎる値を指定すると競合が激しい場合にトランザクションがブロックへ取り込まれない可能性があります。 -トランザクション内のアカウントに対して支払われた最後の優先料金を取得するには、`getRecentPrioritizationFees` RPC呼び出しを使用できます。結果を使用して、上位100件の支払済み料金に基づく平均を計算します。この数値は経験に応じて調整できます。 +トランザクション内のアカウントに対して最近支払われた優先料金は、`getRecentPrioritizationFees` RPC呼び出しで取得できます。ここでは、支払われた料金の上位100件に基づいて平均を計算します。この件数は経験に応じて調整できます。 必要な手順: -1. トランザクションから書き込み可能なアカウントを抽出 -2. それらのアカウントに対して最近支払われた料金を照会 -3. 市場条件に基づいて最適な料金を計算 +1. トランザクションから書き込み可能なアカウントを抽出します +2. それらのアカウントに対して最近支払われた料金を照会します +3. 市場の状況に基づいて最適な料金を計算します -ページの下部に、これを使ったSol転送の完全な例があります。 +ページ下部には、この処理を使用したSOL転送の完全な例があります。 {% totem %} {% totem-accordion title="Code Snippet" %} @@ -63,8 +94,8 @@ export const getPriorityFee = async ( umi: Umi, transaction: TransactionBuilder ): Promise => { - // ステップ1:トランザクションに関与するユニークな書き込み可能アカウントを取得 - // 優先料金に影響するのは書き込み可能アカウントのみなので、それらのみを対象とする + // Step 1: Get unique writable accounts involved in the transaction + // We only care about writable accounts since they affect priority fees const distinctPublicKeys = new Set(); transaction.items.forEach(item => { @@ -75,7 +106,7 @@ export const getPriorityFee = async ( }); }); - // ステップ2:これらのアカウントの最近の優先料金をRPCから照会 + // Step 2: Query recent prioritization fees for these accounts from the RPC const response = await fetch(umi.rpc.getEndpoint(), { method: "POST", headers: { "Content-Type": "application/json" }, @@ -95,7 +126,7 @@ export const getPriorityFee = async ( result: { prioritizationFee: number; slot: number; }[]; }; - // ステップ3:上位100件の料金の平均を計算して競争力のある料金を取得 + // Step 3: Calculate average of top 100 fees to get a competitive rate const fees = data.result?.map(entry => entry.prioritizationFee) || []; const topFees = fees.sort((a, b) => b - a).slice(0, 100); const averageFee = topFees.length > 0 ? Math.ceil( @@ -108,27 +139,27 @@ export const getPriorityFee = async ( {% /totem-accordion %} {% /totem %} -### コンピュートユニットの計算 -トランザクションコストを最適化し、信頼できる実行を確保するために、まずトランザクションをシミュレートして理想的なコンピュートユニット制限を計算できます。このアプローチは固定値を使用するよりも正確で、リソースの過度な割り当てを避けるのに役立ちます。 +### コンピュートユニットを計算する +トランザクションコストを最適化し、信頼性の高い実行を確保するには、最初にトランザクションをシミュレーションして、理想的なコンピュートユニット制限を計算します。この方法は固定値を使用するより正確で、リソースの過剰割り当てを防ぐのに役立ちます。 -シミュレーションプロセスの動作: -1. 最大コンピュートユニット(1,400,000)でトランザクションを構築 -2. シミュレートして実際に消費されるコンピュートユニットを測定 -3. バリエーションを考慮して10%の安全バッファを追加 -4. シミュレーションが失敗した場合は保守的なデフォルトにフォールバック +シミュレーションの手順: +1. 最大コンピュートユニット(1,400,000)でトランザクションを構築します +2. シミュレーションして、実際に消費されるコンピュートユニットを測定します +3. 変動を考慮して10%の安全バッファを追加します +4. シミュレーションが失敗した場合は、保守的なデフォルト値へフォールバックします {% totem %} {% totem-accordion title="Code Snippet" %} ```js export const getRequiredCU = async ( umi: Umi, - transaction: Transaction // ステップ1:トランザクションを渡す + transaction: Transaction // Step 1: pass the transaction ): Promise => { - // 推定が失敗した場合のデフォルト値 - const DEFAULT_COMPUTE_UNITS = 800_000; // 標準的な安全な値 - const BUFFER_FACTOR = 1.1; // 10%の安全マージンを追加 + // Default values if estimation fails + const DEFAULT_COMPUTE_UNITS = 800_000; // Standard safe value + const BUFFER_FACTOR = 1.1; // Add 10% safety margin - // ステップ2:トランザクションをシミュレートして実際に必要なコンピュートユニットを取得 + // Step 2: Simulate the transaction to get actual compute units needed const response = await fetch(umi.rpc.getEndpoint(), { method: "POST", headers: { "Content-Type": "application/json" }, @@ -154,38 +185,43 @@ export const getRequiredCU = async ( const data = await response.json(); const unitsConsumed = data.result?.value?.unitsConsumed; - // シミュレーションがコンピュートユニットを提供しない場合はデフォルトにフォールバック + // Fallback to default if simulation doesn't provide compute units if (!unitsConsumed) { console.log("Simulation didn't return compute units, using default value"); return DEFAULT_COMPUTE_UNITS; } - // 推定されたコンピュートユニットに安全バッファを追加 - return Math.ceil(unitsConsumed * BUFFER_FACTOR); // ステップ3:バッファを使用 + // Add a safety buffer without exceeding the V1 maximum. + const bufferedUnits = Math.ceil(unitsConsumed * BUFFER_FACTOR); + if (bufferedUnits > 1_400_000) { + throw new Error( + `Transaction requires ${bufferedUnits} compute units after buffering, so it cannot fit within the V1 maximum of 1,400,000. Split it into multiple transactions.` + ); + } + return bufferedUnits; // Step 3: use the buffer }; - const withCU = baseTransaction.prepend( - setComputeUnitPrice(umi, { microLamports: priorityFee }) - ).prepend( - setComputeUnitLimit(umi, { units: 1400000 }) - ); + const withCU = baseTransaction + .useV1() + .setTransactionConfig({ computeUnitLimit: 1_400_000 }); - // ステップ8:最適なコンピュートユニット制限を計算 + // Step 8: Calculate optimal compute unit limit console.log("Estimating required compute units..."); const requiredUnits = await getRequiredCU(umi, withCU.build(umi)); ``` {% /totem-accordion %} {% /totem %} -### Sol転送の完全な例 -上記のコードに従い、Umiインスタンスを作成するためのボイラープレートを導入すると、Sol転送トランザクションを作成する以下のようなスクリプトが作成できます: +### SOL転送の完全な例 +上記のコードにUmiインスタンスを作成するためのボイラープレートを加えると、SOL転送トランザクションを作成する次のようなスクリプトになります。 {% totem %} {% totem-accordion title="Full Code Example" %} ```js import { createUmi } from "@metaplex-foundation/umi-bundle-defaults"; import { + lamports, sol, publicKey, Transaction, @@ -196,25 +232,23 @@ import { } from "@metaplex-foundation/umi"; import { transferSol, - setComputeUnitLimit, - setComputeUnitPrice, mplToolbox, } from "@metaplex-foundation/mpl-toolbox"; import { base58, base64 } from "@metaplex-foundation/umi/serializers"; /** - * 最近のトランザクションに基づいて最適な優先料金を計算 - * 適切な料金を提供することで、トランザクションが迅速に処理されることを確保する - * @param umi - Umiインスタンス - * @param transaction - 料金を計算するトランザクション - * @returns マイクロラムポートでの平均優先料金(1ラムポート = 0.000000001 SOL) + * Calculates the optimal priority fee based on recent transactions + * This helps ensure our transaction gets processed quickly by offering an appropriate fee + * @param umi - The Umi instance + * @param transaction - The transaction to calculate the fee for + * @returns The average priority fee in microLamports (1 lamport = 0.000000001 SOL) */ export const getPriorityFee = async ( umi: Umi, transaction: TransactionBuilder ): Promise => { - // トランザクションに関与するユニークな書き込み可能アカウントを取得 - // 優先料金に影響するのは書き込み可能アカウントのみなので、それらのみを対象とする + // Get unique writable accounts involved in the transaction + // We only care about writable accounts since they affect priority fees const distinctPublicKeys = new Set(); transaction.items.forEach(item => { @@ -225,7 +259,7 @@ export const getPriorityFee = async ( }); }); - // これらのアカウントの最近の優先料金をRPCから照会 + // Query recent prioritization fees for these accounts from the RPC const response = await fetch(umi.rpc.getEndpoint(), { method: "POST", headers: { "Content-Type": "application/json" }, @@ -245,7 +279,7 @@ export const getPriorityFee = async ( result: { prioritizationFee: number; slot: number; }[]; }; - // 上位100件の料金の平均を計算して競争力のある料金を取得 + // Calculate average of top 100 fees to get a competitive rate const fees = data.result?.map(entry => entry.prioritizationFee) || []; const topFees = fees.sort((a, b) => b - a).slice(0, 100); const averageFee = topFees.length > 0 ? Math.ceil( @@ -255,21 +289,21 @@ export const getPriorityFee = async ( }; /** - * トランザクションに必要なコンピュートユニットを推定 - * コストを効率的に保ちながら、コンピュートユニット割り当てエラーを防ぐ - * @param umi - Umiインスタンス - * @param transaction - コンピュートユニットを推定するトランザクション - * @returns 10%の安全バッファ付きの推定必要コンピュートユニット + * Estimates the required compute units for a transaction + * This helps prevent compute unit allocation errors while being cost-efficient + * @param umi - The Umi instance + * @param transaction - The transaction to estimate compute units for + * @returns Estimated compute units needed with 10% safety buffer */ export const getRequiredCU = async ( umi: Umi, transaction: Transaction ): Promise => { - // 推定が失敗した場合のデフォルト値 - const DEFAULT_COMPUTE_UNITS = 800_000; // 標準的な安全な値 - const BUFFER_FACTOR = 1.1; // 10%の安全マージンを追加 + // Default values if estimation fails + const DEFAULT_COMPUTE_UNITS = 800_000; // Standard safe value + const BUFFER_FACTOR = 1.1; // Add 10% safety margin - // トランザクションをシミュレートして実際に必要なコンピュートユニットを取得 + // Simulate the transaction to get actual compute units needed const response = await fetch(umi.rpc.getEndpoint(), { method: "POST", headers: { "Content-Type": "application/json" }, @@ -295,38 +329,44 @@ export const getRequiredCU = async ( const data = await response.json(); const unitsConsumed = data.result?.value?.unitsConsumed; - // シミュレーションがコンピュートユニットを提供しない場合はデフォルトにフォールバック + // Fallback to default if simulation doesn't provide compute units if (!unitsConsumed) { console.log("Simulation didn't return compute units, using default value"); return DEFAULT_COMPUTE_UNITS; } - // 推定されたコンピュートユニットに安全バッファを追加 - return Math.ceil(unitsConsumed * BUFFER_FACTOR); + // Add a safety buffer without exceeding the V1 maximum. + const bufferedUnits = Math.ceil(unitsConsumed * BUFFER_FACTOR); + if (bufferedUnits > 1_400_000) { + throw new Error( + `Transaction requires ${bufferedUnits} compute units after buffering, so it cannot fit within the V1 maximum of 1,400,000. Split it into multiple transactions.` + ); + } + return bufferedUnits; }; /** - * 使用例:最適化されたコンピュートユニットと優先料金でSOLを送信する方法のデモンストレーション - * この例では、Solanaトランザクションの作成と最適化の完全なフローを示します + * Example usage: Demonstrates how to send SOL with optimized compute units and priority fees + * This example shows a complete flow of creating and optimizing a Solana transaction */ const example = async () => { - // ステップ1:RPCエンドポイントでUmiを初期化 + // Step 1: Initialize Umi with your RPC endpoint const umi = createUmi("YOUR-ENDPOINT").use(mplToolbox()); - // ステップ2:テストウォレットのセットアップ + // Step 2: Set up a test wallet const signer = generateSigner(umi); umi.use(keypairIdentity(signer)); - // ステップ3:ウォレットに資金を供給(devnetのみ) + // Step 3: Fund the wallet (devnet only) console.log("Requesting airdrop for testing..."); await umi.rpc.airdrop(signer.publicKey, sol(0.001)); - await new Promise(resolve => setTimeout(resolve, 15000)); // エアドロップ確認を待機 + await new Promise(resolve => setTimeout(resolve, 15000)); // Wait for airdrop confirmation - // ステップ4:基本的な転送パラメータのセットアップ + // Step 4: Set up the basic transfer parameters const destination = publicKey("BeeryDvghgcKPTUw3N3bdFDFFWhTWdWHnsLuVebgsGSD"); const transferAmount = sol(0.00001); // 0.00001 SOL - // ステップ5:基本トランザクションの作成 + // Step 5: Create the base transaction console.log("Creating base transfer transaction..."); const baseTransaction = await transferSol(umi, { source: signer, @@ -334,38 +374,47 @@ const example = async () => { amount: transferAmount, }).setLatestBlockhash(umi); - // ステップ6:最適な優先料金の計算 + // Step 6: Calculate optimal priority fee console.log("Calculating optimal priority fee..."); const priorityFee = await getPriorityFee(umi, baseTransaction); - // ステップ7:コンピュートユニット推定のための中間トランザクションの作成 - const withCU = baseTransaction.prepend( - setComputeUnitPrice(umi, { microLamports: priorityFee }) - ).prepend( - setComputeUnitLimit(umi, { units: 1400000 }) - ); + // Step 7: Create intermediate transaction for compute unit estimation + const withCU = baseTransaction + .useV1() + .setTransactionConfig({ computeUnitLimit: 1_400_000 }); - // ステップ8:最適なコンピュートユニット制限の計算 + // Step 8: Calculate optimal compute unit limit console.log("Estimating required compute units..."); const requiredUnits = await getRequiredCU(umi, withCU.build(umi)); - // ステップ9:最終的な最適化されたトランザクションの構築 - const finalTransaction = baseTransaction.prepend( - setComputeUnitPrice(umi, { microLamports: priorityFee }) - ).prepend( - setComputeUnitLimit(umi, { units: requiredUnits }) + // Step 9: Build the final optimized transaction + const totalPriorityFeeLamports = Math.ceil( + (priorityFee * requiredUnits) / 1_000_000 ); - console.log(`Transaction optimized with Priority Fee: ${priorityFee} microLamports and ${requiredUnits} compute units`); + const finalTransaction = baseTransaction + .useV1() + .setTransactionConfig({ + computeUnitLimit: requiredUnits, + priorityFee: lamports(totalPriorityFeeLamports), + }); + console.log(`Transaction optimized with a total priority fee of ${totalPriorityFeeLamports} lamports and ${requiredUnits} compute units`); - // ステップ10:トランザクションの送信と確認 + // Step 10: Send and confirm the transaction console.log("Sending optimized transaction..."); const signature = await finalTransaction.sendAndConfirm(umi); console.log("Transaction confirmed! Signature:", base58.deserialize(signature.signature)[0]); }; -// 例を実行 +// Run the example example().catch(console.error); ``` {% /totem-accordion %} {% /totem %} + +## 注意事項 + +- このガイドはUmi 1.6.0以降とV1トランザクションを対象としています。 +- `TransactionV1Config.priorityFee`はラムポート単位の合計金額ですが、`getRecentPrioritizationFees`はコンピュートユニットあたりのマイクロラムポート単位の価格を返します。 +- V1トランザクションはAddress Lookup TablesやCompute Budget命令をサポートしません。 +- 既存のV0トランザクションビルダーを変換する場合は、[V0からV1トランザクションへの移行](/dev-tools/umi/guides/migrate-to-transaction-v1)を参照してください。 diff --git a/src/pages/ja/dev-tools/umi/toolbox/priority-fees-and-compute-managment.md b/src/pages/ja/dev-tools/umi/toolbox/priority-fees-and-compute-managment.md index 8a4e1c33f..241658cf1 100644 --- a/src/pages/ja/dev-tools/umi/toolbox/priority-fees-and-compute-managment.md +++ b/src/pages/ja/dev-tools/umi/toolbox/priority-fees-and-compute-managment.md @@ -1,39 +1,81 @@ --- title: 優先料金とコンピュート管理 metaTitle: 優先料金とコンピュート管理 | Toolbox -description: Umiで優先料金とコンピュートバジェットプログラムを使用する方法。 +description: UmiのV1およびV0トランザクションにコンピュートユニット制限と優先料金を設定します。 +keywords: + - Umi priority fees + - Umi compute units + - TransactionV1Config + - Compute Budget Program +about: + - Umi + - Solana Transaction Fees +proficiencyLevel: Intermediate +programmingLanguage: + - JavaScript + - TypeScript +created: '09-04-2024' +updated: '09-21-2026' --- -コンピュートバジェットプログラムにより、カスタムコンピュートユニット制限と価格を設定できます。このプログラムについては、[Solanaの公式ドキュメント](https://docs.solana.com/developing/programming-model/runtime#compute-budget)で詳しく読むことができます。 +## まとめ -## コンピュートユニット制限の設定 +V1トランザクションのコンピュートユニットと優先料金は、`setTransactionConfig()`で設定します。 -この命令により、トランザクションにカスタムコンピュートユニット制限を設定できます。 +- V1では`computeUnitLimit`と合計`priorityFee`を使用します。 +- UmiのV1トランザクションビルダーはCompute Budgetプログラム命令を拒否します。 +- V0では`setComputeUnitLimit`と`setComputeUnitPrice`を使用します。 +- コンピュートユニットあたりのマイクロラムポートで表される優先料金の見積もりは、V1では合計ラムポートに変換する必要があります。 -```ts -import { transactionBuilder } from '@metaplex-foundation/umi' -import { setComputeUnitLimit } from '@metaplex-foundation/mpl-toolbox' +UmiのV1トランザクションではコンピュート制限と優先料金の合計をトランザクションメッセージに格納し、V0トランザクションではCompute Budgetプログラム命令を使用します。 + +## V1のコンピュートユニットと優先料金を設定する + +V1トランザクションでは、`setTransactionConfig()`を使用してコンピュートユニット制限と優先料金の合計を設定します。 + +```ts {% title="V1 compute configuration" %} +import { lamports, transactionBuilder } from '@metaplex-foundation/umi' await transactionBuilder() - .add(setComputeUnitLimit(umi, { units: 600_000 })) // コンピュートユニット制限を設定。 - .add(...) // ここに任意の命令。 + .add(myInstruction) + .useV1() + .setTransactionConfig({ + computeUnitLimit: 600_000, + priorityFee: lamports(600), + }) .sendAndConfirm(umi) ``` -## コンピュートユニット価格 / 優先料金の設定 +`priorityFee`はコンピュートユニットあたりの価格ではなく、料金の合計です。価格が1,000マイクロラムポート、制限が600,000ユニットの場合、合計は`600,000 × 1,000 ÷ 1,000,000 = 600`ラムポートです。 + +{% callout type="warning" %} +V1トランザクションビルダーに`setComputeUnitLimit`命令や`setComputeUnitPrice`命令を追加しないでください。UmiはV1トランザクション内のCompute Budget命令を拒否します。 +{% /callout %} + +## V0のコンピュートユニットと優先料金を設定する -この命令により、トランザクションのコンピュートユニットごとにカスタム価格を設定できます。 +V0トランザクションでは、引き続き`@metaplex-foundation/mpl-toolbox`のCompute Budgetプログラム命令を使用します。 -```ts +```ts {% title="V0 compute configuration" %} import { transactionBuilder } from '@metaplex-foundation/umi' -import { setComputeUnitPrice } from '@metaplex-foundation/mpl-toolbox' +import { + setComputeUnitLimit, + setComputeUnitPrice, +} from '@metaplex-foundation/mpl-toolbox' await transactionBuilder() - .add(setComputeUnitPrice(umi, { microLamports: 1 })) // コンピュートユニットあたりの価格をマイクロラムポートで設定。 - .add(...) // ここに任意の命令。 + .add(setComputeUnitLimit(umi, { units: 600_000 })) + .add(setComputeUnitPrice(umi, { microLamports: 1_000 })) + .add(myInstruction) + .useV0() .sendAndConfirm(umi) ``` -{% callout title="unitsとmicroLamportsの計算方法のガイド" type="note" %} -`microLamports`と`units`に適切な数値を選択できるよう、計算に使用できるさまざまなRPC呼び出しを説明する[小さなガイド](/ja/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees)が作成されました。 -{% /callout %} +トランザクションで[Address Lookup Table](/dev-tools/umi/toolbox/address-lookup-table)が必要な場合、または接続されたウォレットがV1トランザクションをサポートしていない場合はV0を使用してください。 + +## 注意事項 + +- `useV1()`と`setTransactionConfig()`を使用するにはUmi 1.6.0以降が必要です。 +- V1のコンピュートユニット制限は1,400,000を超えることができません。 +- コンピュートユニットと料金の見積もりについては、[トランザクション実行の最適化](/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees)を参照してください。 +- すべての互換性要件については、[V0からV1トランザクションへの移行](/dev-tools/umi/guides/migrate-to-transaction-v1)を参照してください。 diff --git a/src/pages/ja/smart-contracts/bubblegum-v2/mint-cnfts.md b/src/pages/ja/smart-contracts/bubblegum-v2/mint-cnfts.md index df192028d..410f51a40 100644 --- a/src/pages/ja/smart-contracts/bubblegum-v2/mint-cnfts.md +++ b/src/pages/ja/smart-contracts/bubblegum-v2/mint-cnfts.md @@ -149,7 +149,7 @@ await createCollection(umi, { {% /dialect %} {% /dialect-switcher %} -## コレクションからロイヤリティを継承する +## コレクションからロイヤリティを継承する {% #inheriting-royalties-from-the-collection %} MPL-Coreコレクションにミントする場合、コレクションのロイヤリティ率をすべてのcNFTにコピーする代わりに、リーフに**センチネル**のセラーフィーベーシスポイント値(`65535`、`SELLER_FEE_BASIS_POINTS_INHERIT` / `0xffff` としてエクスポート)を保存できます。DASは表示用に `royalty.basis_points` / `creators` にコレクションから解決された料率を置き、`royalty.basis_points_raw` / `creators_raw` にリーフセンチネルを置き(`royalty.inherited: true`)、オンチェーンのリーフはハッシュ化のためにセンチネルを保持します。 diff --git a/src/pages/ja/solana/solana-transaction-fundamentals.md b/src/pages/ja/solana/solana-transaction-fundamentals.md index 47d855b2b..1466ce023 100644 --- a/src/pages/ja/solana/solana-transaction-fundamentals.md +++ b/src/pages/ja/solana/solana-transaction-fundamentals.md @@ -1,30 +1,30 @@ --- -title: Solana Transaction Fundamentals -metaTitle: Solana Transaction Fundamentals | How Transactions Work -description: Learn how Solana transactions work, including structure, signing, sending, and confirmation. Essential knowledge for building reliable applications. +title: Solanaトランザクションの基礎 +metaTitle: Solanaトランザクションの基礎 | トランザクションの仕組み +description: 構造、署名、送信、確認を含むSolanaトランザクションの仕組みを学びます。信頼性の高いアプリケーションを構築するために欠かせない知識です。 # remember to update dates also in /components/products/guides/index.js created: '02-04-2026' -updated: null +updated: '09-21-2026' --- -A comprehensive guide to understanding how Solana transactions work from structure to confirmation. {% .lead %} +構造から確認まで、Solanaトランザクションの仕組みを包括的に解説します。 {% .lead %} -## What You'll Learn +## このガイドで学ぶこと -- The anatomy of a Solana transaction -- How to sign and send transactions -- Transaction confirmation and finality -- Versioned transactions vs legacy -- Common transaction errors and their meanings +- Solanaトランザクションの構造 +- トランザクションに署名して送信する方法 +- トランザクションの確認とファイナリティ +- バージョン付きトランザクションとlegacyトランザクションの違い +- 一般的なトランザクションエラーとその意味 -## Prerequisites +## 前提条件 -- [Solana CLI installed](/solana/solana-cli-essentials) -- [Understanding Solana accounts](/solana/understanding-solana-accounts) +- [Solana CLIのインストール](/solana/solana-cli-essentials) +- [Solanaアカウントの理解](/solana/understanding-solana-accounts) -## Transaction Anatomy +## トランザクションの構造 -A Solana transaction consists of several components: +Solanaトランザクションは複数のコンポーネントで構成されます。 ``` ┌─────────────────────────────────────────────────────────────┐ @@ -49,22 +49,22 @@ A Solana transaction consists of several components: └─────────────────────────────────────────────────────────────┘ ``` -### Key Components +### 主要コンポーネント -| Component | Description | +| コンポーネント | 説明 | |-----------|-------------| -| **Signatures** | Ed25519 signatures from required signers | -| **Recent Blockhash** | A recent block hash (valid for ~60-90 seconds) | -| **Instructions** | The operations to perform | -| **Account Keys** | All accounts involved in the transaction | +| **Signatures** | 必要な署名者によるEd25519署名 | +| **Recent Blockhash** | 最近のブロックハッシュ(約60〜90秒間有効) | +| **Instructions** | 実行する処理 | +| **Account Keys** | トランザクションに関与するすべてのアカウント | -## Instructions +## 命令 -Instructions are the actual operations in a transaction. Each instruction specifies: +命令はトランザクション内で実際に実行される処理です。各命令は次の項目を指定します。 -- **Program ID** - Which program to execute -- **Accounts** - Which accounts the program needs -- **Data** - Serialized arguments for the program +- **Program ID** - 実行するプログラム +- **Accounts** - プログラムが必要とするアカウント +- **Data** - プログラムに渡すシリアライズ済み引数 ``` Instruction: @@ -75,9 +75,9 @@ Instruction: └── data: [encoded transfer amount] ``` -### Multiple Instructions +### 複数の命令 -Transactions can contain multiple instructions that execute atomically: +トランザクションには、アトミックに実行される複数の命令を含めることができます。 ```javascript import { transactionBuilder } from '@metaplex-foundation/umi' @@ -91,14 +91,14 @@ const builder = transactionBuilder() await builder.sendAndConfirm(umi) ``` -This atomicity is powerful. If any instruction fails, the entire transaction is reverted. +このアトミック性により、いずれかの命令が失敗するとトランザクション全体がロールバックされます。 ## Recent Blockhash -Every transaction requires a **recent blockhash** that: -- Proves the transaction was created recently -- Prevents replay attacks -- Expires after ~60-90 seconds (~150 slots) +すべてのトランザクションには、次の役割を持つ**recent blockhash**が必要です。 +- トランザクションが最近作成されたことを証明する +- リプレイ攻撃を防ぐ +- 約60〜90秒後(約150スロット後)に期限切れになる ```javascript // UMI handles blockhash automatically when sending transactions. @@ -106,13 +106,13 @@ Every transaction requires a **recent blockhash** that: const { blockhash, lastValidBlockHeight } = await umi.rpc.getLatestBlockhash() ``` -{% callout title="Blockhash Expiration" type="warning" %} -If your transaction isn't confirmed before the blockhash expires, it will be dropped. For long-running operations, fetch a fresh blockhash before sending. +{% callout title="ブロックハッシュの期限切れ" type="warning" %} +ブロックハッシュの期限が切れる前にトランザクションが確認されなければ、そのトランザクションは破棄されます。時間のかかる処理では、送信前に新しいブロックハッシュを取得してください。 {% /callout %} -## Signing Transactions +## トランザクションへの署名 -Transactions must be signed by all accounts marked as `isSigner`: +トランザクションには、`isSigner`と指定されたすべてのアカウントによる署名が必要です。 ```javascript // UMI signs automatically with the identity signer when sending. @@ -130,9 +130,9 @@ const encoded = base64.deserialize(serialized)[0] // ... send encoded string to another party for additional signing ... ``` -## Sending Transactions +## トランザクションの送信 -### Basic Send +### 基本的な送信 ```javascript // Send and wait for confirmation (recommended) @@ -142,7 +142,7 @@ const result = await myBuilder.sendAndConfirm(umi) const signature = await myBuilder.send(umi) ``` -### Send with Options +### オプションを指定した送信 ```javascript const result = await myBuilder.sendAndConfirm(umi, { @@ -151,17 +151,17 @@ const result = await myBuilder.sendAndConfirm(umi, { }) ``` -## Transaction Confirmation +## トランザクションの確認 -Solana has multiple **commitment levels** indicating transaction finality: +Solanaには、トランザクションのファイナリティを示す複数の**commitment level**があります。 -| Commitment | Description | Use Case | +| Commitment | 説明 | ユースケース | |------------|-------------|----------| -| `processed` | Transaction received by leader | Real-time updates | -| `confirmed` | Voted on by supermajority | Most applications | -| `finalized` | 31+ blocks deep, irreversible | Financial operations | +| `processed` | リーダーがトランザクションを受信済み | リアルタイム更新 | +| `confirmed` | スーパーマジョリティによる投票済み | ほとんどのアプリケーション | +| `finalized` | 31ブロック以上経過し、不可逆 | 金融処理 | -### Checking Confirmation +### 確認状況を調べる ```javascript // sendAndConfirm waits for confirmation automatically. @@ -169,7 +169,7 @@ Solana has multiple **commitment levels** indicating transaction finality: const result = await umi.rpc.getSignatureStatuses([signature]) ``` -### Commitment in Practice +### 実際のCommitment指定 ```javascript // For most operations, 'confirmed' is the right default @@ -183,24 +183,38 @@ const result = await myBuilder.sendAndConfirm(umi, { }) ``` -## Versioned Transactions +## バージョン付きトランザクション -Solana currently supports two transaction formats: +Solanaは3つのトランザクション形式をサポートしています。 -### Legacy Transactions -- Original format -- Limited to 35 accounts -- Simpler structure +### Legacyトランザクション -### Versioned Transactions (v0) -- Support **Address Lookup Tables** (ALTs) -- Can reference up to 256 accounts -- Required for complex DeFi operations +Legacyトランザクションは、Address Lookup Tablesを使用しないSolanaの元来のトランザクション形式です。 + +- 元来の形式 +- 最大35アカウント +- より単純な構造 + +### V0トランザクション + +V0トランザクションは、より多くのアカウントを必要とするトランザクション向けにAddress Lookup Tableをサポートします。 + +- **Address Lookup Tables**(ALT)をサポート +- 最大256アカウントを参照可能 +- 複雑なDeFi処理で必要 + +### V1トランザクション + +V1トランザクションではトランザクションのサイズ上限が増え、コンピュート設定がメッセージ内に格納されます。 + +- 最大4,096バイトのトランザクションをサポート +- コンピュートバジェット設定をトランザクションメッセージ内に格納 +- Address Lookup Tablesはサポートしない ```javascript -// UMI uses V0 transactions by default +// Umi uses V0 transactions by default. Opt in to V1 explicitly. const result = await myBuilder - .useV0() // Explicit, but this is already the default + .useV1() .sendAndConfirm(umi) // To use legacy transactions instead @@ -217,40 +231,44 @@ const [lutBuilder, lut] = createLut(umi, { }) await lutBuilder.sendAndConfirm(umi) -// Use the lookup table in your transaction -await myBuilder.setAddressLookupTables([lut]).sendAndConfirm(umi) +// Address Lookup Tables require V0. +await myBuilder + .useV0() + .setAddressLookupTables([lut]) + .sendAndConfirm(umi) ``` -{% callout title="When to Use Versioned Transactions" %} -Use versioned transactions when: -- Your transaction involves many accounts (>35) -- You're interacting with DeFi protocols that require ALTs -- You want to reduce transaction size +{% callout title="トランザクションバージョンの選び方" %} +- ウォレットがトランザクションバージョン`1`をサポートし、トランザクションが1,232バイトを超える場合はV1を使用します。 +- トランザクションにAddress Lookup Tableが必要な場合はV0を使用します。 +- 互換性のために元来の形式が必要な場合にのみlegacyトランザクションを使用します。 -For simple operations (transfers, basic mints), legacy transactions work fine. +後方互換性のため、UmiのデフォルトはV0です。アプリケーション全体のデフォルトを変更する前に、[V0からV1トランザクションへの移行](/dev-tools/umi/guides/migrate-to-transaction-v1)を参照してください。 {% /callout %} -## Transaction Size Limits +## トランザクションのサイズ制限 -Solana transactions have strict size limits: +Solanaトランザクションには厳格なサイズ制限があります。 -| Limit | Value | +| 制限 | 値 | |-------|-------| -| Maximum transaction size | 1232 bytes | -| Maximum accounts | 35 (legacy) / 256 (versioned with ALTs) | -| Maximum instructions | Limited by size | +| LegacyおよびV0トランザクションのサイズ | 1,232バイト | +| V1トランザクションのサイズ | 4,096バイト | +| Address Lookup Tables | V0のみ | +| 命令の最大数 | サイズによる制限 | -### Dealing with Size Limits +### サイズ制限への対処 -If your transaction is too large: +トランザクションが大きすぎる場合は、次の方法で対処します。 -1. **Use Address Lookup Tables** - Compress account references -2. **Split into multiple transactions** - Execute sequentially -3. **Optimize instruction data** - Minimize serialized data +1. **V1を使用する** - Address Lookup Tableが不要な場合、サイズ上限を4,096バイトに増やす +2. **V0でAddress Lookup Tablesを使用する** - アカウント参照を圧縮する +3. **複数のトランザクションに分割する** - 順番に実行する +4. **命令データを最適化する** - シリアライズされるデータを最小化する -## Simulation +## シミュレーション -Before sending, simulate transactions to catch errors: +送信前にトランザクションをシミュレーションしてエラーを検出します。 ```javascript // Build the transaction without sending @@ -265,27 +283,27 @@ const simulation = await umi.rpc.simulateTransaction(tx, { console.log('Simulation result:', simulation) ``` -Simulation helps you: -- Catch errors before paying fees -- Estimate compute units -- Debug program logic +シミュレーションには次の利点があります。 +- 料金を支払う前にエラーを検出できる +- コンピュートユニットを見積もれる +- プログラムロジックをデバッグできる -## Common Transaction Errors +## 一般的なトランザクションエラー ### "Blockhash not found" -**Cause**: The blockhash expired before confirmation. +**原因**:確認前にブロックハッシュの期限が切れています。 -**Solutions**: -1. Retry with a fresh blockhash (UMI fetches a new blockhash automatically on each send) -2. Use `'finalized'` commitment for blockhash when network is congested -3. Implement retry logic in your application +**解決方法**: +1. 新しいブロックハッシュで再試行します(UMIは送信のたびに新しいブロックハッシュを自動取得します) +2. ネットワーク混雑時には、ブロックハッシュに`'finalized'` commitmentを使用します +3. アプリケーションに再試行ロジックを実装します ### "Insufficient funds" -**Cause**: Account doesn't have enough SOL for transaction fees + rent. +**原因**:アカウントにトランザクション料金とrentを支払うための十分なSOLがありません。 -**Solution**: Ensure the fee payer has sufficient balance: +**解決方法**:fee payerに十分な残高があることを確認します。 ```bash solana balance solana airdrop 1 # On devnet @@ -293,23 +311,23 @@ solana airdrop 1 # On devnet ### "Transaction simulation failed" -**Cause**: Program logic error. +**原因**:プログラムロジックのエラーです。 -**Solution**: Check simulation logs on an explorer (see [Using Solana Explorers](/solana/using-solana-explorers)), or simulate the transaction before sending to inspect the error output. +**解決方法**:[Solana Explorerの使用](/solana/using-solana-explorers)を参照してExplorerでシミュレーションログを確認するか、送信前にトランザクションをシミュレーションしてエラー出力を調べます。 ### "Account not found" -**Cause**: An account in the transaction doesn't exist. +**原因**:トランザクション内のアカウントが存在しません。 -**Solution**: Create the account first or check addresses. +**解決方法**:先にアカウントを作成するか、アドレスを確認します。 ### "Invalid account owner" -**Cause**: Account is owned by a different program than expected. +**原因**:アカウントが想定とは異なるプログラムによって所有されています。 -**Solution**: Verify account ownership matches the program you're calling. +**解決方法**:アカウントの所有者が呼び出し先のプログラムと一致することを確認します。 -## Practical Example: Complete Flow +## 実践例:完全なフロー ```javascript import { createUmi } from '@metaplex-foundation/umi-bundle-defaults' @@ -337,26 +355,26 @@ console.log('Transaction confirmed:', signature) console.log(`Explorer: https://explorer.solana.com/tx/${signature}?cluster=devnet`) ``` -## Next Steps +## 次のステップ -- [Compute units and priority fees](/solana/compute-units-and-priority-fees) - Optimize transaction landing -- [Working with devnet and testnet](/solana/working-with-devnet-and-testnet) - Test your transactions -- [Diagnose transaction errors](/solana/general/how-to-diagnose-solana-transaction-errors) - Debug failed transactions +- [コンピュートユニットと優先料金](/solana/compute-units-and-priority-fees) - トランザクション実行を最適化する +- [devnetとtestnetの使用](/solana/working-with-devnet-and-testnet) - トランザクションをテストする +- [トランザクションエラーの診断](/solana/general/how-to-diagnose-solana-transaction-errors) - 失敗したトランザクションをデバッグする ## FAQ -### How long do I have to confirm a transaction? +### トランザクションを確認できる時間はどのくらいですか? -A transaction's blockhash is valid for approximately 60-90 seconds (~150 slots). After that, the transaction will be dropped if not confirmed. +トランザクションのブロックハッシュは約60〜90秒間(約150スロット)有効です。その時間を過ぎても確認されなかったトランザクションは破棄されます。 -### Can I cancel a transaction? +### トランザクションをキャンセルできますか? -No, once submitted, you cannot cancel a transaction. However, if it hasn't been confirmed, you can submit a new transaction with the same nonce (using durable nonces) to effectively "replace" it. +いいえ。一度送信したトランザクションはキャンセルできません。ただし、まだ確認されていない場合は、durable nonceを使用して同じnonceの新しいトランザクションを送信し、実質的に「置き換える」ことができます。 -### What's the difference between "processed" and "confirmed"? +### "processed"と"confirmed"の違いは何ですか? -"Processed" means a validator received it. "Confirmed" means a supermajority (66%+) of validators voted on the block containing it. Always use "confirmed" or "finalized" for important operations. +"Processed"は、バリデーターがトランザクションを受信したことを意味します。"Confirmed"は、トランザクションを含むブロックに対してスーパーマジョリティ(66%以上)のバリデーターが投票したことを意味します。重要な処理には必ず"confirmed"または"finalized"を使用してください。 -### Why did my transaction fail after simulation succeeded? +### シミュレーションが成功した後にトランザクションが失敗したのはなぜですか? -State can change between simulation and execution. Another transaction may have modified the accounts. This is common in competitive scenarios like NFT mints. +シミュレーションと実行の間に状態が変化することがあります。別のトランザクションがアカウントを変更した可能性があります。これはNFTのミントなど、競合が発生する状況でよく起こります。 diff --git a/src/pages/ko/dev-tools/umi/guides/migrate-to-transaction-v1.md b/src/pages/ko/dev-tools/umi/guides/migrate-to-transaction-v1.md new file mode 100644 index 000000000..ba7fd471e --- /dev/null +++ b/src/pages/ko/dev-tools/umi/guides/migrate-to-transaction-v1.md @@ -0,0 +1,268 @@ +--- +title: V0에서 V1 트랜잭션으로 마이그레이션 +metaTitle: V0에서 V1 트랜잭션으로 마이그레이션 | Umi +description: 컴퓨트 예산, 우선순위 수수료, 지갑 호환성을 포함하여 Umi 트랜잭션 빌더와 직접 트랜잭션 생성을 Solana V0 트랜잭션에서 V1 트랜잭션으로 마이그레이션합니다. +keywords: + - Umi transaction v1 + - Solana transaction v1 + - Umi v0 migration + - TransactionV1Config + - useV1 + - setTransactionConfig + - SIMD-0385 +about: + - Umi + - Solana Transaction V1 + - Transaction Migration +proficiencyLevel: Intermediate +programmingLanguage: + - JavaScript + - TypeScript +created: '09-21-2026' +updated: '09-21-2026' +howToSteps: + - Umi 패키지를 1.6.0 이상으로, web3.js를 1.99.0 이상으로 업그레이드합니다 + - 트랜잭션 빌더별로 V1을 선택하거나 애플리케이션 기본값으로 설정합니다 + - Compute Budget 인스트럭션을 TransactionV1Config로 대체합니다 + - Address Lookup Tables가 필요한 트랜잭션은 V0으로 유지합니다 + - 서명 전에 연결된 모든 지갑이 V1 트랜잭션을 지원하는지 확인합니다 +howToTools: + - Umi 1.6.0 or later + - web3.js 1.99.0 or later + - Solana RPC +faqs: + - q: Umi는 기본적으로 V1 트랜잭션을 사용하나요? + a: 아니요. Umi 1.6.0은 이전 버전과의 호환성을 위해 V0을 기본값으로 유지합니다. 트랜잭션 빌더에서 useV1을 호출하거나 Umi를 생성할 때 defaultTransactionVersion을 1로 설정하세요. + - q: Umi V1 트랜잭션에서 Address Lookup Table을 사용할 수 있나요? + a: 아니요. V1 트랜잭션은 Address Lookup Tables를 지원하지 않습니다. Address Lookup Table이 필요한 트랜잭션은 V0으로 유지하세요. + - q: V1 트랜잭션에 Compute Budget 프로그램 인스트럭션을 포함할 수 있나요? + a: 아니요. Umi는 Compute Budget 인스트럭션이 포함된 V1 트랜잭션 빌더를 거부합니다. setTransactionConfig를 사용하여 컴퓨트 유닛 제한, 총 우선순위 수수료, 로드된 계정 데이터 크기 제한 또는 힙 크기를 설정하세요. + - q: V1 트랜잭션 우선순위 수수료는 컴퓨트 유닛당 가격인가요? + a: 아니요. TransactionV1Config.priorityFee는 SolAmount로 나타낸 총 우선순위 수수료입니다. 마이크로 램포트 가격에 컴퓨트 유닛 제한을 곱하고 1,000,000으로 나눈 다음 램포트 단위로 올림하여 변환하세요. + - q: 모든 Solana 지갑이 V1 트랜잭션을 지원하나요? + a: 아니요. Umi는 지갑 어댑터용 V1 트랜잭션을 직렬화할 수 있지만, 연결된 지갑이 트랜잭션 버전 1을 수락하고 서명할 수 있어야 합니다. V1을 애플리케이션 전체 기본값으로 설정하기 전에 지갑 지원 여부를 확인하세요. +--- + +Umi 애플리케이션을 V0에서 [V1 트랜잭션](https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0385-transaction-v1.md)으로 마이그레이션하여 더 큰 트랜잭션을 사용하고 트랜잭션 메시지에서 컴퓨트 예산을 직접 구성할 수 있습니다. {% .lead %} + +{% callout title="마이그레이션할 항목" %} +이 가이드에서는 Umi V0 트랜잭션 빌더를 V1으로 전환하고, Compute Budget 인스트럭션을 `TransactionV1Config`로 대체하며, V1을 전역으로 구성하고, V0으로 유지해야 하는 트랜잭션을 식별합니다. +{% /callout %} + +## 요약 + +Umi 1.6.0은 `useV1()`, `defaultTransactionVersion: 1`, 직접 트랜잭션 입력의 `version: 1`을 통해 선택적으로 V1 트랜잭션을 지원합니다. + +- V1은 직렬화된 트랜잭션 제한을 1,232바이트에서 4,096바이트로 늘립니다. +- V1은 컴퓨트 제한과 총 우선순위 수수료를 `TransactionV1Config`에 저장합니다. +- V1은 Address Lookup Tables 또는 Compute Budget 인스트럭션을 지원하지 않습니다. +- Umi는 계속 V0을 기본값으로 사용하며, 연결된 지갑이 V1을 지원해야 합니다. + +## 빠른 시작 + +트랜잭션 빌더에서 V1을 선택하고 Compute Budget 인스트럭션을 `setTransactionConfig()`로 대체하세요. + +1. Umi 1.6.0 이상 및 `@solana/web3.js` 1.99.0 이상으로 업그레이드합니다. +2. 트랜잭션 빌더에 `.useV1()`을 추가합니다. +3. `setComputeUnitLimit` 및 `setComputeUnitPrice` 인스트럭션을 제거합니다. +4. `.setTransactionConfig({ computeUnitLimit, priorityFee })`를 추가합니다. +5. 애플리케이션에서 지원하는 모든 지갑으로 V1 서명을 테스트합니다. + +**바로 가기:** [사전 요구 사항](#사전-요구-사항) · [V0 및 V1의 차이점](#v0-및-v1-트랜잭션의-차이점) · [빌더 마이그레이션](#트랜잭션-빌더를-v1으로-마이그레이션) · [애플리케이션 기본값](#v1을-애플리케이션-기본값으로-설정) · [직접 생성](#직접-트랜잭션-생성을-v1으로-마이그레이션) · [Address Lookup Tables](#address-lookup-table-트랜잭션을-v0으로-유지) · [일반적인 오류](#일반적인-v1-마이그레이션-오류) · [FAQ](#faq) + +## 사전 요구 사항 + +V1 마이그레이션에는 호환되는 Umi, Web3.js, RPC 및 지갑 버전이 필요합니다. + +| 구성 요소 | 요구 사항 | +|-----------|-------------| +| Umi packages | 1.6.0 이상 | +| `@solana/web3.js` | 1.99.0 이상 | +| Solana clusters | mainnet-beta, devnet 및 testnet에서 V1 활성화 | +| Wallet | 트랜잭션 버전 `1`을 수락하고 서명해야 함 | + +{% callout type="warning" %} +연결된 모든 지갑 경로가 트랜잭션 버전 `1`을 지원하기 전에는 V1을 전역으로 활성화하지 마세요. Umi는 지갑 어댑터용 트랜잭션을 직렬화하지만, 호환되지 않는 지갑이 트랜잭션에 서명하도록 만들 수는 없습니다. +{% /callout %} + +## V0 및 V1 트랜잭션의 차이점 + +V1은 트랜잭션 크기 제한을 늘리지만 V0 Address Lookup Tables 또는 Compute Budget 인스트럭션을 지원하지 않습니다. + +| 기능 | V0 | V1 | +|------------|----------------|----------------| +| 직렬화 크기 제한 | 1,232바이트 | 4,096바이트 | +| Address lookup tables | 지원 | 지원하지 않음 | +| 컴퓨트 유닛 제한 | Compute Budget 인스트럭션 | `transactionConfig.computeUnitLimit` | +| 우선순위 수수료 | 컴퓨트 유닛당 마이크로 램포트 | `transactionConfig.priorityFee`의 총 `SolAmount` | +| Umi 1.6.0 기본값 | 예 | 아니요, 명시적으로 선택해야 함 | +| 빌더 선택자 | `useV0()` | `useV1()` | + +V1은 Address Lookup Table에 의존하지 않으면서 트랜잭션이 V0 크기 제한을 초과할 때 가장 유용합니다. + +## 트랜잭션 빌더를 V1으로 마이그레이션 + +V0 트랜잭션 빌더는 Compute Budget 인스트럭션을 `useV1()` 및 `setTransactionConfig()`로 대체하여 V1으로 마이그레이션할 수 있습니다. + +### 마이그레이션 전 V0 트랜잭션 빌더 + +V0 트랜잭션 빌더는 컴퓨트 유닛 제한과 가격을 인스트럭션으로 표현합니다. + +```typescript {% title="transaction-v0.ts" %} +import { transactionBuilder } from '@metaplex-foundation/umi' +import { + setComputeUnitLimit, + setComputeUnitPrice, + transferSol, +} from '@metaplex-foundation/mpl-toolbox' + +await transactionBuilder() + .add(setComputeUnitLimit(umi, { units: 600_000 })) + .add(setComputeUnitPrice(umi, { microLamports: 1_000 })) + .add(transferSol(umi, transferArgs)) + .sendAndConfirm(umi) +``` + +### 마이그레이션 후 V1 트랜잭션 빌더 + +V1 트랜잭션 빌더는 컴퓨트 유닛 제한과 총 우선순위 수수료를 트랜잭션 메시지에 표현합니다. + +```typescript {% title="transaction-v1.ts" %} +import { lamports, transactionBuilder } from '@metaplex-foundation/umi' +import { transferSol } from '@metaplex-foundation/mpl-toolbox' + +await transactionBuilder() + .add(transferSol(umi, transferArgs)) + .useV1() + .setTransactionConfig({ + computeUnitLimit: 600_000, + priorityFee: lamports(600), + }) + .sendAndConfirm(umi) +``` + +총 수수료 `600`램포트는 `600,000 × 1,000 ÷ 1,000,000`과 같습니다. 변환 결과가 정수 램포트가 아니면 올림하세요. + +{% callout type="note" %} +`setTransactionConfig()`는 전체 구성을 대체합니다. 개별 필드로 반복 호출하지 말고 모든 사용자 지정 V1 설정을 한 번의 호출에 포함하세요. +{% /callout %} + +## V1을 애플리케이션 기본값으로 설정 + +`defaultTransactionVersion: 1`을 설정하면 빌더가 다른 버전을 명시적으로 선택하지 않는 한 모든 트랜잭션 빌더가 V1을 사용합니다. + +```typescript {% title="umi.ts" %} +import { createUmi } from '@metaplex-foundation/umi-bundle-defaults' + +const umi = createUmi('https://api.mainnet-beta.solana.com', { + defaultTransactionVersion: 1, +}) +``` + +이 옵션은 Metaplex 프로그램 라이브러리가 반환하는 빌더에도 적용됩니다. `useV0()`을 호출하는 빌더는 여전히 애플리케이션 기본값을 재정의합니다. + +트랜잭션 팩토리를 직접 설치하는 애플리케이션은 대신 플러그인을 구성할 수 있습니다. + +```typescript {% title="umi-with-custom-plugins.ts" %} +import { web3JsTransactionFactory } from '@metaplex-foundation/umi-transaction-factory-web3js' + +umi.use(web3JsTransactionFactory({ defaultTransactionVersion: 1 })) +``` + +## 직접 트랜잭션 생성을 V1으로 마이그레이션 + +직접 `umi.transactions.create()`를 호출할 때는 `version: 1`을 설정하고 0이 아닌 런타임 제한을 명시적으로 제공해야 합니다. + +```typescript {% title="create-transaction-v1.ts" %} +const transaction = umi.transactions.create({ + version: 1, + blockhash: (await umi.rpc.getLatestBlockhash()).blockhash, + instructions: [myInstruction], + payer: umi.payer.publicKey, + transactionConfig: { + computeUnitLimit: 200_000, + loadedAccountsDataSizeLimit: 64 * 1024 * 1024, + }, +}) +``` + +`TransactionBuilder`는 생략된 컴퓨트 및 로드된 계정 제한에 대해 레거시와 동일한 기본값을 제공합니다. 저수준 `create()` 메서드는 기본값을 제공하지 않으며, 생략된 제한은 런타임에서 0으로 처리됩니다. + +## V1 트랜잭션 제한 구성 + +`TransactionV1Config`는 컴퓨트, 계정 데이터, 힙 크기 및 총 우선순위 수수료를 제어합니다. + +| 필드 | 의미 | 유효 범위 또는 동작 | +|-------|---------|-------------------------| +| `computeUnitLimit` | 최대 컴퓨트 유닛 | `0`부터 `1,400,000`까지의 정수 | +| `priorityFee` | 총 우선순위 수수료 | 일반적으로 `lamports(...)`로 생성하는 `SolAmount` | +| `loadedAccountsDataSizeLimit` | 로드된 계정 데이터의 최대 크기 | 최대 64MiB | +| `heapSize` | 프로그램 힙 프레임 크기 | 1,024바이트 단위로 32,768~262,144바이트 | + +빌더는 해당 필드가 생략되면 `computeUnitLimit`의 기본값을 `min(200,000 × 인스트럭션 수, 1,400,000)`으로, `loadedAccountsDataSizeLimit`의 기본값을 64MiB로 설정합니다. + +## Address Lookup Table 트랜잭션을 V0으로 유지 + +[Address Lookup Tables](/dev-tools/umi/toolbox/address-lookup-table)가 필요한 트랜잭션은 V0으로 유지해야 합니다. + +```typescript {% title="transaction-v0-with-lookup-table.ts" %} +const builder = transactionBuilder() + .add(myInstruction) + .useV0() + .setAddressLookupTables([myLookupTable]) +``` + +트랜잭션을 V1으로 강제 전환하기 위해 Address Lookup Table을 제거하지 마세요. 컴파일된 계정 목록과 직렬화 크기를 비교한 다음 트랜잭션 요구 사항을 충족하는 형식을 사용하세요. + +## 사용자 지정 Umi 통합 업데이트 + +사용자 지정 트랜잭션 팩토리와 모든 버전을 빠짐없이 처리하는 코드는 Umi 1.6.0으로 업그레이드할 때 V1 지원을 추가해야 합니다. + +- 사용자 지정 `TransactionFactoryInterface` 구현에 `getDefaultVersion()`을 구현합니다. +- `TransactionVersion`을 완전하게 분기하는 코드에 `1` 케이스를 추가합니다. +- 이제 V0 버전 필드가 필수이므로 직접 생성하는 V0 `TransactionInput` 객체에 `version: 0`을 추가합니다. +- 트랜잭션을 읽을 때 `transaction.message.version`을 확인합니다. V1 메시지에는 `transactionConfig`가 포함됩니다. + +Umi의 RPC 통합은 `maxSupportedTransactionVersion: 1`을 요청하므로 `umi.rpc.getTransaction()`으로 V1 트랜잭션을 가져올 수 있습니다. + +## 일반적인 V1 마이그레이션 오류 + +Umi는 호환되지 않는 빌더 조합을 트랜잭션 전송 전에 거부합니다. + +| 오류 | 원인 | 해결 방법 | +|-------|-------|-----| +| `V1 transactions ignore ComputeBudget instructions. Set the compute budget with setTransactionConfig instead.` | V1 트랜잭션 빌더에 `setComputeUnitLimit`, `setComputeUnitPrice` 또는 다른 Compute Budget 인스트럭션이 포함됨 | 인스트럭션을 제거하고 `setTransactionConfig()` 사용 | +| `Address lookup tables are not supported by V1 transactions.` | V1 트랜잭션 빌더에 하나 이상의 Address Lookup Tables가 있음 | 빌더를 V0으로 유지하거나 lookup table 요구 사항 제거 | +| `Transaction configs are only supported by V1 transactions.` | 레거시 또는 V0 트랜잭션 빌더가 `setTransactionConfig()`를 호출함 | `useV1()`을 호출하거나 V0에서 Compute Budget 인스트럭션 사용 | +| 지갑이 트랜잭션을 거부하거나 역직렬화하지 못함 | 지갑이 트랜잭션 버전 `1`을 지원하지 않음 | 지갑이 V1 지원을 추가할 때까지 해당 지갑 흐름을 V0으로 유지 | +| 직접 생성한 트랜잭션이 불충분한 컴퓨트 예산으로 실패함 | `create()`에 `computeUnitLimit`이 전달되지 않음 | 0이 아닌 `transactionConfig.computeUnitLimit` 설정 | + +## 참고 사항 + +- V1은 Umi 1.6.0에서 선택적으로 사용하며, 이전 버전과의 호환성을 위해 기본값은 V0으로 유지됩니다. +- V1은 2026년 9월 15일 epoch 1035부터 Solana mainnet-beta에서 활성화되었습니다. +- 전송 및 시뮬레이션은 1,232바이트보다 큰 V1 트랜잭션을 지원하는 base64 인코딩을 사용합니다. +- Umi는 직렬화 전에 컴퓨트 유닛 제한과 힙 크기를 검증합니다. +- 구현 및 호환성 세부 정보는 [metaplex-foundation/umi#216](https://github.com/metaplex-foundation/umi/pull/216)에 문서화되어 있습니다. + +## FAQ + +### Umi는 기본적으로 V1 트랜잭션을 사용하나요? + +Umi 1.6.0은 이전 버전과의 호환성을 위해 V0을 기본값으로 유지합니다. 트랜잭션 빌더에서 `useV1()`을 호출하거나 Umi를 생성할 때 `defaultTransactionVersion: 1`을 설정하세요. + +### Umi V1 트랜잭션에서 Address Lookup Table을 사용할 수 있나요? + +V1 트랜잭션은 Address Lookup Tables를 지원하지 않습니다. Address Lookup Table이 필요한 트랜잭션은 V0으로 유지하세요. + +### V1 트랜잭션에 Compute Budget 프로그램 인스트럭션을 포함할 수 있나요? + +Umi는 Compute Budget 인스트럭션이 포함된 V1 트랜잭션 빌더를 거부합니다. `setTransactionConfig()`를 사용하여 컴퓨트 유닛 제한, 총 우선순위 수수료, 로드된 계정 데이터 크기 제한 또는 힙 크기를 설정하세요. + +### V1 트랜잭션 우선순위 수수료는 컴퓨트 유닛당 가격인가요? + +`TransactionV1Config.priorityFee`는 컴퓨트 유닛당 가격이 아니라 `SolAmount`로 나타낸 총 우선순위 수수료입니다. 마이크로 램포트 가격에 컴퓨트 유닛 제한을 곱하고 1,000,000으로 나눈 다음 램포트 단위로 올림하여 변환하세요. + +### 모든 Solana 지갑이 V1 트랜잭션을 지원하나요? + +트랜잭션 버전 `1`에 대한 지갑 지원은 보편적이지 않습니다. Umi는 지갑 어댑터용 V1 트랜잭션을 직렬화할 수 있지만, 연결된 지갑이 트랜잭션을 수락하고 서명할 수 있어야 합니다. diff --git a/src/pages/ko/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees.md b/src/pages/ko/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees.md index 3b7e5092b..e89e51f53 100644 --- a/src/pages/ko/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees.md +++ b/src/pages/ko/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees.md @@ -1,55 +1,86 @@ --- title: 컴퓨트 유닛(CU)과 우선순위 수수료를 사용한 최적 트랜잭션 랜딩 metaTitle: Umi - 컴퓨트 유닛(CU)과 우선순위 수수료를 사용한 최적 트랜잭션 랜딩 -description: 적절한 컴퓨트 유닛(CU)과 우선순위 수수료를 계산하고 설정하여 Solana 트랜잭션을 최적화하는 방법을 배우세요. +description: 적절한 컴퓨트 유닛(CU)과 우선순위 수수료를 계산하고 설정하여 Solana 트랜잭션을 최적화하는 방법을 알아봅니다. +keywords: + - Umi transaction v1 + - compute units + - priority fees + - transaction optimization +about: + - Umi + - Solana Transaction V1 + - Priority Fees +proficiencyLevel: Intermediate +programmingLanguage: + - JavaScript + - TypeScript created: '12-02-2024' -updated: '12-02-2024' +updated: '09-21-2026' --- -Solana에서 트랜잭션을 전송할 때, 두 가지 핵심 매개변수를 최적화하면 트랜잭션의 성공률과 비용 효율성을 크게 향상시킬 수 있습니다: +## 요약 + +Umi V1 트랜잭션은 시뮬레이션을 사용해 컴퓨트 소비량을 추정하고 컴퓨트 제한과 총 우선순위 수수료를 `TransactionV1Config`에 저장합니다. + +- 1,400,000 컴퓨트 유닛 제한으로 시뮬레이션합니다. +- 소비된 유닛에 안전 여유분을 추가합니다. +- 컴퓨트 유닛당 마이크로 램포트 단위로 시장 가격을 추정합니다. +- `setTransactionConfig()`를 호출하기 전에 추정치를 총 램포트 수수료로 변환합니다. + +Solana에서 트랜잭션을 전송할 때 두 가지 핵심 매개변수를 최적화하면 트랜잭션의 성공률과 비용 효율성을 크게 높일 수 있습니다. + +## 빠른 시작 + +트랜잭션을 전송하기 전에 V1 컴퓨트 제한과 총 우선순위 수수료를 추정하세요. + +1. 트랜잭션의 쓰기 가능 계정에 최근 지불된 수수료를 기준으로 [우선순위 수수료를 추정](#우선순위-수수료)합니다. +2. 최대 V1 컴퓨트 제한으로 [트랜잭션을 시뮬레이션](#컴퓨트-유닛-제한)합니다. +3. `setTransactionConfig()`로 [추정값을 적용](#구현-가이드)합니다. +4. [SOL 전송 전체 예시](#sol-전송-전체-예시)를 실행합니다. ## 우선순위 수수료 -우선순위 수수료를 통해 로컬 수수료 시장에서 입찰하여 트랜잭션이 더 빠르게 포함되도록 할 수 있습니다. 네트워크가 혼잡하고 여러 트랜잭션이 동일한 계정을 수정하려고 경쟁할 때, 검증자들은 더 높은 우선순위 수수료를 가진 트랜잭션을 우선시합니다. +우선순위 수수료를 사용하면 로컬 수수료 시장에서 입찰하여 트랜잭션이 더 빠르게 포함되도록 할 수 있습니다. 네트워크가 혼잡하고 여러 트랜잭션이 동일한 계정을 수정하려고 경쟁할 때 검증자는 우선순위 수수료가 더 높은 트랜잭션을 우선 처리합니다. -우선순위 수수료에 대한 핵심 사항: -- 다음과 같이 계산됩니다: `compute_unit_limit * compute_unit_price` -- 더 높은 수수료는 더 빠른 포함 가능성을 증가시킵니다 -- 현재 네트워크 경쟁에 기반하여 필요한 만큼만 지불하세요 +우선순위 수수료의 핵심 사항은 다음과 같습니다. +- 계산식은 `compute_unit_limit * compute_unit_price`입니다. +- 수수료가 높을수록 더 빠르게 포함될 가능성이 커집니다. +- 현재 네트워크 경쟁 상황에 따라 필요한 만큼만 지불해야 합니다. ## 컴퓨트 유닛 제한 -컴퓨트 유닛(CU)은 트랜잭션에 필요한 계산 리소스를 나타냅니다. 트랜잭션이 안전 조치로 기본적으로 많은 CU를 요청하지만, 이는 종종 비효율적입니다: +Compute Units(CU)는 트랜잭션에 필요한 계산 리소스를 나타냅니다. 트랜잭션은 안전을 위해 기본적으로 많은 CU를 요청하지만 이는 비효율적인 경우가 많습니다. -1. 실제 사용량에 관계없이 요청한 모든 CU에 대해 우선순위 수수료를 지불합니다 -2. 블록은 제한된 CU 용량을 가집니다 - 과도한 CU를 요청하면 블록당 총 트랜잭션 수가 줄어듭니다 +1. 실제 사용량과 관계없이 요청한 모든 CU에 대해 우선순위 수수료를 지불합니다. +2. 블록의 CU 용량은 제한되어 있으므로 과도한 CU 요청은 블록당 총 트랜잭션 수를 줄입니다. -CU 제한 최적화의 이점: -- 필요한 CU에 대해서만 지불하여 트랜잭션 비용 절감 -- 블록당 더 많은 트랜잭션을 허용하여 네트워크 효율성 개선 -- 실행에 충분한 리소스를 여전히 보장 +CU 제한 최적화의 이점은 다음과 같습니다. +- 필요한 CU에 대해서만 지불하여 트랜잭션 비용을 낮춥니다. +- 블록당 더 많은 트랜잭션을 허용하여 네트워크 효율성을 높입니다. +- 실행에 충분한 리소스를 계속 보장합니다. -예를 들어, 간단한 토큰 전송은 20,000 CU만 필요할 수 있지만, NFT 민팅은 100,000 CU가 필요할 수 있습니다. 이러한 제한을 적절히 설정하면 비용과 전체 네트워크 처리량을 모두 최적화하는 데 도움이 됩니다. +예를 들어 간단한 토큰 전송에는 20,000CU만 필요할 수 있지만 NFT 민팅에는 100,000CU가 필요할 수 있습니다. 이러한 제한을 적절히 설정하면 비용과 전체 네트워크 처리량을 모두 최적화할 수 있습니다. ## 구현 가이드 -이 가이드는 추측하기보다는 프로그래밍적으로 최적 값을 계산하는 방법을 보여줍니다. +이 가이드에서는 값을 추측하는 대신 프로그래밍 방식으로 최적값을 계산하는 방법을 보여줍니다. {% callout type="warning" %} -코드 예시는 Umi가 아직 이러한 메서드를 구현하지 않았기 때문에 RPC 호출에 `fetch`를 사용합니다. 공식 지원이 추가되면 Umi의 내장 메서드를 사용하는 것이 좋습니다. +Umi가 아직 이러한 메서드를 구현하지 않았으므로 코드 예시는 RPC 호출에 `fetch`를 사용합니다. 공식 지원이 추가되면 Umi의 내장 메서드를 우선 사용하세요. {% /callout %} ### 우선순위 수수료 계산 -우선순위 수수료를 사용할 때는 경쟁이 고려될 때 가장 좋은 효과를 낸다는 점을 기억하는 것이 중요합니다. 수동으로 큰 숫자를 추가하면 필요 이상으로 많은 수수료를 지불할 수 있고, 너무 낮은 숫자를 사용하면 경쟁이 너무 치열한 경우 트랜잭션이 블록에 포함되지 않을 수 있습니다. +우선순위 수수료는 경쟁 상황을 고려할 때 가장 효과적입니다. 매우 큰 값을 수동으로 추가하면 필요 이상으로 수수료를 지불할 수 있고, 값이 너무 낮으면 경쟁이 심할 때 트랜잭션이 블록에 포함되지 않을 수 있습니다. -우리 트랜잭션의 계정에 대해 지불된 마지막 우선순위화 수수료를 얻으려면 `getRecentPrioritizationFees` RPC 호출을 사용할 수 있습니다. 결과를 사용하여 지불된 상위 100개 수수료를 기반으로 평균을 계산합니다. 이 숫자는 경험에 따라 조정할 수 있습니다. +트랜잭션의 계정에 대해 최근 지불된 우선순위 수수료를 가져오려면 `getRecentPrioritizationFees` RPC 호출을 사용할 수 있습니다. 이 예시는 결과 중 상위 100개 수수료를 기준으로 평균을 계산합니다. 이 수치는 경험에 따라 조정할 수 있습니다. -다음 단계가 필요합니다: -1. 트랜잭션에서 쓰기 가능한 계정 추출 -2. 해당 계정에 대해 지불된 최근 수수료 쿼리 -3. 시장 상황에 기반한 최적 수수료 계산 +필요한 단계는 다음과 같습니다. +1. 트랜잭션에서 쓰기 가능 계정을 추출합니다. +2. 해당 계정에 최근 지불된 수수료를 조회합니다. +3. 시장 상황에 따라 최적 수수료를 계산합니다. -페이지 하단에서 이를 사용하여 Sol Transfer를 수행하는 전체 예시를 찾을 수 있습니다. +페이지 아래쪽에서 이 방식을 사용해 SOL을 전송하는 전체 예시를 확인할 수 있습니다. {% totem %} {% totem-accordion title="코드 스니펫" %} @@ -63,8 +94,8 @@ export const getPriorityFee = async ( umi: Umi, transaction: TransactionBuilder ): Promise => { - // 1단계: 트랜잭션에 포함된 고유한 쓰기 가능 계정 가져오기 - // 우선순위 수수료에 영향을 주는 쓰기 가능한 계정만 고려합니다 + // Step 1: Get unique writable accounts involved in the transaction + // We only care about writable accounts since they affect priority fees const distinctPublicKeys = new Set(); transaction.items.forEach(item => { @@ -75,7 +106,7 @@ export const getPriorityFee = async ( }); }); - // 2단계: RPC에서 이러한 계정에 대한 최근 우선순위화 수수료 쿼리 + // Step 2: Query recent prioritization fees for these accounts from the RPC const response = await fetch(umi.rpc.getEndpoint(), { method: "POST", headers: { "Content-Type": "application/json" }, @@ -95,7 +126,7 @@ export const getPriorityFee = async ( result: { prioritizationFee: number; slot: number; }[]; }; - // 3단계: 경쟁력 있는 비율을 얻기 위해 상위 100개 수수료의 평균 계산 + // Step 3: Calculate average of top 100 fees to get a competitive rate const fees = data.result?.map(entry => entry.prioritizationFee) || []; const topFees = fees.sort((a, b) => b - a).slice(0, 100); const averageFee = topFees.length > 0 ? Math.ceil( @@ -103,31 +134,32 @@ export const getPriorityFee = async ( ) : 0; return averageFee; }; + ``` {% /totem-accordion %} {% /totem %} ### 컴퓨트 유닛 계산 -트랜잭션 비용을 최적화하고 안정적인 실행을 보장하기 위해 먼저 트랜잭션을 시뮬레이션하여 이상적인 컴퓨트 유닛 제한을 계산할 수 있습니다. 이 접근법은 고정 값을 사용하는 것보다 더 정확하고 리소스의 과도한 할당을 피하는 데 도움이 됩니다. +트랜잭션 비용을 최적화하고 안정적인 실행을 보장하려면 먼저 트랜잭션을 시뮬레이션하여 이상적인 컴퓨트 유닛 제한을 계산할 수 있습니다. 이 방식은 고정값을 사용하는 것보다 정밀하며 리소스 과다 할당을 방지하는 데 도움이 됩니다. -시뮬레이션 프로세스는 다음과 같이 작동합니다: -1. 최대 컴퓨트 유닛(1,400,000)으로 트랜잭션 구축 -2. 실제 소비된 컴퓨트 유닛을 측정하기 위해 시뮬레이션 -3. 변동을 고려하여 10% 안전 버퍼 추가 -4. 시뮬레이션이 실패하면 보수적인 기본값으로 대체 +시뮬레이션 과정은 다음과 같습니다. +1. 최대 컴퓨트 유닛(1,400,000)으로 트랜잭션을 빌드합니다. +2. 실제 소비된 컴퓨트 유닛을 측정하도록 시뮬레이션합니다. +3. 변동을 고려하여 10% 안전 버퍼를 추가합니다. +4. 시뮬레이션이 실패하면 보수적인 기본값을 사용합니다. {% totem %} {% totem-accordion title="코드 스니펫" %} ```js export const getRequiredCU = async ( umi: Umi, - transaction: Transaction // 1단계: 트랜잭션 전달 + transaction: Transaction // Step 1: pass the transaction ): Promise => { - // 추정이 실패할 경우 기본값 - const DEFAULT_COMPUTE_UNITS = 800_000; // 표준 안전 값 - const BUFFER_FACTOR = 1.1; // 10% 안전 마진 추가 + // Default values if estimation fails + const DEFAULT_COMPUTE_UNITS = 800_000; // Standard safe value + const BUFFER_FACTOR = 1.1; // Add 10% safety margin - // 2단계: 필요한 실제 컴퓨트 유닛을 얻기 위해 트랜잭션 시뮬레이션 + // Step 2: Simulate the transaction to get actual compute units needed const response = await fetch(umi.rpc.getEndpoint(), { method: "POST", headers: { "Content-Type": "application/json" }, @@ -153,38 +185,43 @@ export const getRequiredCU = async ( const data = await response.json(); const unitsConsumed = data.result?.value?.unitsConsumed; - // 시뮬레이션이 컴퓨트 유닛을 제공하지 않으면 기본값으로 대체 + // Fallback to default if simulation doesn't provide compute units if (!unitsConsumed) { console.log("Simulation didn't return compute units, using default value"); return DEFAULT_COMPUTE_UNITS; } - // 추정된 컴퓨트 유닛에 안전 버퍼 추가 - return Math.ceil(unitsConsumed * BUFFER_FACTOR); // 3단계: 버퍼 사용 + // Add a safety buffer without exceeding the V1 maximum. + const bufferedUnits = Math.ceil(unitsConsumed * BUFFER_FACTOR); + if (bufferedUnits > 1_400_000) { + throw new Error( + `Transaction requires ${bufferedUnits} compute units after buffering, so it cannot fit within the V1 maximum of 1,400,000. Split it into multiple transactions.` + ); + } + return bufferedUnits; // Step 3: use the buffer }; - const withCU = baseTransaction.prepend( - setComputeUnitPrice(umi, { microLamports: priorityFee }) - ).prepend( - setComputeUnitLimit(umi, { units: 1400000 }) - ); + const withCU = baseTransaction + .useV1() + .setTransactionConfig({ computeUnitLimit: 1_400_000 }); - // 8단계: 최적 컴퓨트 유닛 제한 계산 + // Step 8: Calculate optimal compute unit limit console.log("Estimating required compute units..."); const requiredUnits = await getRequiredCU(umi, withCU.build(umi)); ``` {% /totem-accordion %} {% /totem %} -### Sol Transfer의 전체 예시 -위의 코드를 따르고 Umi 인스턴스를 생성하기 위한 일부 상용구를 도입하면 Sol Transfer 트랜잭션을 생성하는 다음과 같은 스크립트가 나올 수 있습니다: +### SOL 전송 전체 예시 +위 코드를 사용하고 Umi 인스턴스를 생성하는 기본 코드를 추가하면 다음과 같은 스크립트로 SOL 전송 트랜잭션을 만들 수 있습니다. {% totem %} {% totem-accordion title="전체 코드 예시" %} ```js import { createUmi } from "@metaplex-foundation/umi-bundle-defaults"; import { + lamports, sol, publicKey, Transaction, @@ -195,25 +232,23 @@ import { } from "@metaplex-foundation/umi"; import { transferSol, - setComputeUnitLimit, - setComputeUnitPrice, mplToolbox, } from "@metaplex-foundation/mpl-toolbox"; import { base58, base64 } from "@metaplex-foundation/umi/serializers"; /** - * 최근 트랜잭션을 기반으로 최적 우선순위 수수료를 계산합니다 - * 이는 적절한 수수료를 제공하여 트랜잭션이 빠르게 처리되도록 도움을 줍니다 - * @param umi - Umi 인스턴스 - * @param transaction - 수수료를 계산할 트랜잭션 - * @returns 마이크로램포트 단위의 평균 우선순위 수수료 (1 람포트 = 0.000000001 SOL) + * Calculates the optimal priority fee based on recent transactions + * This helps ensure our transaction gets processed quickly by offering an appropriate fee + * @param umi - The Umi instance + * @param transaction - The transaction to calculate the fee for + * @returns The average priority fee in microLamports (1 lamport = 0.000000001 SOL) */ export const getPriorityFee = async ( umi: Umi, transaction: TransactionBuilder ): Promise => { - // 트랜잭션에 포함된 고유한 쓰기 가능 계정 가져오기 - // 우선순위 수수료에 영향을 주는 쓰기 가능한 계정만 고려합니다 + // Get unique writable accounts involved in the transaction + // We only care about writable accounts since they affect priority fees const distinctPublicKeys = new Set(); transaction.items.forEach(item => { @@ -224,7 +259,7 @@ export const getPriorityFee = async ( }); }); - // RPC에서 이러한 계정에 대한 최근 우선순위화 수수료 쿼리 + // Query recent prioritization fees for these accounts from the RPC const response = await fetch(umi.rpc.getEndpoint(), { method: "POST", headers: { "Content-Type": "application/json" }, @@ -244,7 +279,7 @@ export const getPriorityFee = async ( result: { prioritizationFee: number; slot: number; }[]; }; - // 경쟁력 있는 비율을 얻기 위해 상위 100개 수수료의 평균 계산 + // Calculate average of top 100 fees to get a competitive rate const fees = data.result?.map(entry => entry.prioritizationFee) || []; const topFees = fees.sort((a, b) => b - a).slice(0, 100); const averageFee = topFees.length > 0 ? Math.ceil( @@ -254,21 +289,21 @@ export const getPriorityFee = async ( }; /** - * 트랜잭션에 필요한 컴퓨트 유닛을 추정합니다 - * 이는 비용 효율적이면서 컴퓨트 유닛 할당 오류를 방지하는 데 도움이 됩니다 - * @param umi - Umi 인스턴스 - * @param transaction - 컴퓨트 유닛을 추정할 트랜잭션 - * @returns 10% 안전 버퍼가 포함된 추정 필요 컴퓨트 유닛 + * Estimates the required compute units for a transaction + * This helps prevent compute unit allocation errors while being cost-efficient + * @param umi - The Umi instance + * @param transaction - The transaction to estimate compute units for + * @returns Estimated compute units needed with 10% safety buffer */ export const getRequiredCU = async ( umi: Umi, transaction: Transaction ): Promise => { - // 추정이 실패할 경우 기본값 - const DEFAULT_COMPUTE_UNITS = 800_000; // 표준 안전 값 - const BUFFER_FACTOR = 1.1; // 10% 안전 마진 추가 + // Default values if estimation fails + const DEFAULT_COMPUTE_UNITS = 800_000; // Standard safe value + const BUFFER_FACTOR = 1.1; // Add 10% safety margin - // 필요한 실제 컴퓨트 유닛을 얻기 위해 트랜잭션 시뮬레이션 + // Simulate the transaction to get actual compute units needed const response = await fetch(umi.rpc.getEndpoint(), { method: "POST", headers: { "Content-Type": "application/json" }, @@ -294,38 +329,44 @@ export const getRequiredCU = async ( const data = await response.json(); const unitsConsumed = data.result?.value?.unitsConsumed; - // 시뮬레이션이 컴퓨트 유닛을 제공하지 않으면 기본값으로 대체 + // Fallback to default if simulation doesn't provide compute units if (!unitsConsumed) { console.log("Simulation didn't return compute units, using default value"); return DEFAULT_COMPUTE_UNITS; } - // 추정된 컴퓨트 유닛에 안전 버퍼 추가 - return Math.ceil(unitsConsumed * BUFFER_FACTOR); + // Add a safety buffer without exceeding the V1 maximum. + const bufferedUnits = Math.ceil(unitsConsumed * BUFFER_FACTOR); + if (bufferedUnits > 1_400_000) { + throw new Error( + `Transaction requires ${bufferedUnits} compute units after buffering, so it cannot fit within the V1 maximum of 1,400,000. Split it into multiple transactions.` + ); + } + return bufferedUnits; }; /** - * 사용 예시: 최적화된 컴퓨트 유닛과 우선순위 수수료로 SOL을 전송하는 방법을 보여줍니다 - * 이 예시는 Solana 트랜잭션을 생성하고 최적화하는 완전한 흐름을 보여줍니다 + * Example usage: Demonstrates how to send SOL with optimized compute units and priority fees + * This example shows a complete flow of creating and optimizing a Solana transaction */ const example = async () => { - // 1단계: RPC 엔드포인트로 Umi 초기화 + // Step 1: Initialize Umi with your RPC endpoint const umi = createUmi("YOUR-ENDPOINT").use(mplToolbox()); - // 2단계: 테스트 지갑 설정 + // Step 2: Set up a test wallet const signer = generateSigner(umi); umi.use(keypairIdentity(signer)); - // 3단계: 지갑에 자금 조달 (devnet만) + // Step 3: Fund the wallet (devnet only) console.log("Requesting airdrop for testing..."); await umi.rpc.airdrop(signer.publicKey, sol(0.001)); - await new Promise(resolve => setTimeout(resolve, 15000)); // 에어드롭 확인 대기 + await new Promise(resolve => setTimeout(resolve, 15000)); // Wait for airdrop confirmation - // 4단계: 기본 전송 매개변수 설정 + // Step 4: Set up the basic transfer parameters const destination = publicKey("BeeryDvghgcKPTUw3N3bdFDFFWhTWdWHnsLuVebgsGSD"); const transferAmount = sol(0.00001); // 0.00001 SOL - // 5단계: 기본 트랜잭션 생성 + // Step 5: Create the base transaction console.log("Creating base transfer transaction..."); const baseTransaction = await transferSol(umi, { source: signer, @@ -333,37 +374,47 @@ const example = async () => { amount: transferAmount, }).setLatestBlockhash(umi); - // 6단계: 최적 우선순위 수수료 계산 + // Step 6: Calculate optimal priority fee console.log("Calculating optimal priority fee..."); const priorityFee = await getPriorityFee(umi, baseTransaction); - // 7단계: 컴퓨트 유닛 추정을 위한 중간 트랜잭션 생성 - const withCU = baseTransaction.prepend( - setComputeUnitPrice(umi, { microLamports: priorityFee }) - ).prepend( - setComputeUnitLimit(umi, { units: 1400000 }) - ); + // Step 7: Create intermediate transaction for compute unit estimation + const withCU = baseTransaction + .useV1() + .setTransactionConfig({ computeUnitLimit: 1_400_000 }); - // 8단계: 최적 컴퓨트 유닛 제한 계산 + // Step 8: Calculate optimal compute unit limit console.log("Estimating required compute units..."); const requiredUnits = await getRequiredCU(umi, withCU.build(umi)); - // 9단계: 최종 최적화된 트랜잭션 구축 - const finalTransaction = baseTransaction.prepend( - setComputeUnitPrice(umi, { microLamports: priorityFee }) - ).prepend( - setComputeUnitLimit(umi, { units: requiredUnits }) + // Step 9: Build the final optimized transaction + const totalPriorityFeeLamports = Math.ceil( + (priorityFee * requiredUnits) / 1_000_000 ); - console.log(`Transaction optimized with Priority Fee: ${priorityFee} microLamports and ${requiredUnits} compute units`); + const finalTransaction = baseTransaction + .useV1() + .setTransactionConfig({ + computeUnitLimit: requiredUnits, + priorityFee: lamports(totalPriorityFeeLamports), + }); + console.log(`Transaction optimized with a total priority fee of ${totalPriorityFeeLamports} lamports and ${requiredUnits} compute units`); - // 10단계: 트랜잭션 전송 및 확인 + // Step 10: Send and confirm the transaction console.log("Sending optimized transaction..."); const signature = await finalTransaction.sendAndConfirm(umi); console.log("Transaction confirmed! Signature:", base58.deserialize(signature.signature)[0]); }; -// 예시 실행 +// Run the example example().catch(console.error); + ``` {% /totem-accordion %} {% /totem %} + +## 참고 사항 + +- 이 가이드는 Umi 1.6.0 이상과 V1 트랜잭션을 대상으로 합니다. +- `TransactionV1Config.priorityFee`는 총 램포트 금액이지만 `getRecentPrioritizationFees`는 컴퓨트 유닛당 마이크로 램포트 가격을 반환합니다. +- V1 트랜잭션은 Address Lookup Tables 또는 Compute Budget 인스트럭션을 지원하지 않습니다. +- 기존 V0 트랜잭션 빌더를 변환하려면 [V0에서 V1 트랜잭션으로 마이그레이션](/dev-tools/umi/guides/migrate-to-transaction-v1)을 참조하세요. diff --git a/src/pages/ko/dev-tools/umi/toolbox/priority-fees-and-compute-managment.md b/src/pages/ko/dev-tools/umi/toolbox/priority-fees-and-compute-managment.md index f536bbb98..ec8ea2a3e 100644 --- a/src/pages/ko/dev-tools/umi/toolbox/priority-fees-and-compute-managment.md +++ b/src/pages/ko/dev-tools/umi/toolbox/priority-fees-and-compute-managment.md @@ -1,39 +1,81 @@ --- title: 우선순위 수수료 및 컴퓨트 관리 metaTitle: 우선순위 수수료 및 컴퓨트 관리 | Toolbox -description: Umi와 함께 우선순위 수수료 및 컴퓨트 예산 프로그램을 사용하는 방법. +description: Umi V1 및 V0 트랜잭션의 컴퓨트 유닛 제한과 우선순위 수수료를 구성합니다. +keywords: + - Umi priority fees + - Umi compute units + - TransactionV1Config + - Compute Budget Program +about: + - Umi + - Solana Transaction Fees +proficiencyLevel: Intermediate +programmingLanguage: + - JavaScript + - TypeScript +created: '09-04-2024' +updated: '09-21-2026' --- -컴퓨트 예산 프로그램을 사용하면 사용자 정의 컴퓨트 유닛 제한과 가격을 설정할 수 있습니다. 이 프로그램에 대한 자세한 내용은 [Solana의 공식 문서](https://docs.solana.com/developing/programming-model/runtime#compute-budget)에서 확인할 수 있습니다. +## 요약 -## 컴퓨트 유닛 제한 설정 +V1 트랜잭션에서 컴퓨트 유닛과 우선순위 수수료를 구성하려면 `setTransactionConfig()`를 사용하세요. -이 인스트럭션을 사용하면 트랜잭션에 대한 사용자 정의 컴퓨트 유닛 제한을 설정할 수 있습니다. +- V1은 `computeUnitLimit`과 총 `priorityFee`를 사용합니다. +- Umi V1 트랜잭션 빌더는 Compute Budget 프로그램 인스트럭션을 거부합니다. +- V0은 `setComputeUnitLimit` 및 `setComputeUnitPrice`를 사용합니다. +- 컴퓨트 유닛당 마이크로 램포트로 표시된 우선순위 수수료 추정치는 V1에서 총 램포트로 변환해야 합니다. -```ts -import { transactionBuilder } from '@metaplex-foundation/umi' -import { setComputeUnitLimit } from '@metaplex-foundation/mpl-toolbox' +Umi V1 트랜잭션은 컴퓨트 제한과 총 우선순위 수수료를 트랜잭션 메시지에 저장하지만, V0 트랜잭션은 Compute Budget 프로그램 인스트럭션을 사용합니다. + +## V1 컴퓨트 유닛 및 우선순위 수수료 구성 + +V1 트랜잭션은 `setTransactionConfig()`로 컴퓨트 유닛 제한과 총 우선순위 수수료를 구성합니다. + +```ts {% title="V1 compute configuration" %} +import { lamports, transactionBuilder } from '@metaplex-foundation/umi' await transactionBuilder() - .add(setComputeUnitLimit(umi, { units: 600_000 })) // 컴퓨트 유닛 제한 설정 - .add(...) // 여기에 모든 인스트럭션들 + .add(myInstruction) + .useV1() + .setTransactionConfig({ + computeUnitLimit: 600_000, + priorityFee: lamports(600), + }) .sendAndConfirm(umi) ``` -## 컴퓨트 유닛 가격 / 우선순위 수수료 설정 +`priorityFee`는 컴퓨트 유닛당 가격이 아니라 총 수수료입니다. 가격이 1,000마이크로 램포트이고 제한이 600,000유닛이면 총액은 `600,000 × 1,000 ÷ 1,000,000 = 600`램포트입니다. + +{% callout type="warning" %} +V1 트랜잭션 빌더에 `setComputeUnitLimit` 또는 `setComputeUnitPrice` 인스트럭션을 추가하지 마세요. Umi는 V1 트랜잭션의 Compute Budget 인스트럭션을 거부합니다. +{% /callout %} + +## V0 컴퓨트 유닛 및 우선순위 수수료 구성 -이 인스트럭션을 사용하면 트랜잭션에 대한 컴퓨트 유닛당 사용자 정의 가격을 설정할 수 있습니다. +V0 트랜잭션은 계속 `@metaplex-foundation/mpl-toolbox`의 Compute Budget 프로그램 인스트럭션을 사용합니다. -```ts +```ts {% title="V0 compute configuration" %} import { transactionBuilder } from '@metaplex-foundation/umi' -import { setComputeUnitPrice } from '@metaplex-foundation/mpl-toolbox' +import { + setComputeUnitLimit, + setComputeUnitPrice, +} from '@metaplex-foundation/mpl-toolbox' await transactionBuilder() - .add(setComputeUnitPrice(umi, { microLamports: 1 })) // 마이크로 람포트 단위로 컴퓨트 유닛당 가격 설정 - .add(...) // 여기에 모든 인스트럭션들 + .add(setComputeUnitLimit(umi, { units: 600_000 })) + .add(setComputeUnitPrice(umi, { microLamports: 1_000 })) + .add(myInstruction) + .useV0() .sendAndConfirm(umi) ``` -{% callout title="유닛과 마이크로람포트 계산 방법 가이드" type="note" %} -`microLamports`와 `units`에 대한 적절한 숫자를 선택할 수 있도록 계산에 사용할 수 있는 다양한 RPC 호출을 안내하는 [간단한 가이드](/ko/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees)가 작성되었습니다. -{% /callout %} +트랜잭션에 [Address Lookup Table](/dev-tools/umi/toolbox/address-lookup-table)이 필요하거나 연결된 지갑이 V1 트랜잭션을 지원하지 않으면 V0을 사용하세요. + +## 참고 사항 + +- `useV1()` 및 `setTransactionConfig()`를 사용하려면 Umi 1.6.0 이상이 필요합니다. +- V1 컴퓨트 유닛 제한은 1,400,000을 초과할 수 없습니다. +- 컴퓨트 유닛과 수수료를 추정하려면 [최적 트랜잭션 랜딩](/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees)을 참조하세요. +- 모든 호환성 요구 사항은 [V0에서 V1 트랜잭션으로 마이그레이션](/dev-tools/umi/guides/migrate-to-transaction-v1)을 참조하세요. diff --git a/src/pages/ko/smart-contracts/bubblegum-v2/mint-cnfts.md b/src/pages/ko/smart-contracts/bubblegum-v2/mint-cnfts.md index b8f322fbf..a6ad2b328 100644 --- a/src/pages/ko/smart-contracts/bubblegum-v2/mint-cnfts.md +++ b/src/pages/ko/smart-contracts/bubblegum-v2/mint-cnfts.md @@ -145,7 +145,7 @@ await createCollection(umi, { {% /dialect %} {% /dialect-switcher %} -## 컬렉션에서 로열티 상속 +## 컬렉션에서 로열티 상속 {% #inheriting-royalties-from-the-collection %} MPL-Core 컬렉션에 민팅할 때 컬렉션의 로열티 비율을 모든 cNFT에 복사하는 대신 리프에 **센티널** seller fee basis points 값(`65535`, `SELLER_FEE_BASIS_POINTS_INHERIT` / `0xffff`로 내보냄)을 저장할 수 있습니다. DAS는 표시용으로 `royalty.basis_points` / `creators`에 컬렉션에서 해석된 비율을 두고, `royalty.basis_points_raw` / `creators_raw`에 리프 센티널을 두며(`royalty.inherited: true`), 온체인 리프는 해싱을 위해 센티널을 유지합니다. diff --git a/src/pages/ko/solana/solana-transaction-fundamentals.md b/src/pages/ko/solana/solana-transaction-fundamentals.md index 47d855b2b..bd34c0662 100644 --- a/src/pages/ko/solana/solana-transaction-fundamentals.md +++ b/src/pages/ko/solana/solana-transaction-fundamentals.md @@ -1,30 +1,30 @@ --- -title: Solana Transaction Fundamentals -metaTitle: Solana Transaction Fundamentals | How Transactions Work -description: Learn how Solana transactions work, including structure, signing, sending, and confirmation. Essential knowledge for building reliable applications. +title: Solana 트랜잭션 기초 +metaTitle: Solana 트랜잭션 기초 | 트랜잭션 작동 방식 +description: 구조, 서명, 전송, 확인을 포함하여 Solana 트랜잭션이 작동하는 방식을 알아봅니다. 안정적인 애플리케이션을 구축하기 위한 필수 지식입니다. # remember to update dates also in /components/products/guides/index.js created: '02-04-2026' -updated: null +updated: '09-21-2026' --- -A comprehensive guide to understanding how Solana transactions work from structure to confirmation. {% .lead %} +구조부터 확인까지 Solana 트랜잭션의 작동 방식을 이해하기 위한 종합 가이드입니다. {% .lead %} -## What You'll Learn +## 학습 내용 -- The anatomy of a Solana transaction -- How to sign and send transactions -- Transaction confirmation and finality -- Versioned transactions vs legacy -- Common transaction errors and their meanings +- Solana 트랜잭션의 구성 +- 트랜잭션에 서명하고 전송하는 방법 +- 트랜잭션 확인과 최종성 +- 버전 트랜잭션과 레거시 트랜잭션의 차이 +- 일반적인 트랜잭션 오류와 그 의미 -## Prerequisites +## 사전 요구 사항 -- [Solana CLI installed](/solana/solana-cli-essentials) -- [Understanding Solana accounts](/solana/understanding-solana-accounts) +- [Solana CLI 설치](/solana/solana-cli-essentials) +- [Solana 계정 이해](/solana/understanding-solana-accounts) -## Transaction Anatomy +## 트랜잭션 구성 -A Solana transaction consists of several components: +Solana 트랜잭션은 여러 구성 요소로 이루어집니다. ``` ┌─────────────────────────────────────────────────────────────┐ @@ -49,22 +49,22 @@ A Solana transaction consists of several components: └─────────────────────────────────────────────────────────────┘ ``` -### Key Components +### 핵심 구성 요소 -| Component | Description | +| 구성 요소 | 설명 | |-----------|-------------| -| **Signatures** | Ed25519 signatures from required signers | -| **Recent Blockhash** | A recent block hash (valid for ~60-90 seconds) | -| **Instructions** | The operations to perform | -| **Account Keys** | All accounts involved in the transaction | +| **Signatures** | 필수 서명자의 Ed25519 서명 | +| **Recent Blockhash** | 최근 블록 해시(약 60~90초 동안 유효) | +| **Instructions** | 수행할 작업 | +| **Account Keys** | 트랜잭션에 관련된 모든 계정 | -## Instructions +## 인스트럭션 -Instructions are the actual operations in a transaction. Each instruction specifies: +인스트럭션은 트랜잭션에서 실제로 수행되는 작업입니다. 각 인스트럭션은 다음을 지정합니다. -- **Program ID** - Which program to execute -- **Accounts** - Which accounts the program needs -- **Data** - Serialized arguments for the program +- **Program ID** - 실행할 프로그램 +- **Accounts** - 프로그램에 필요한 계정 +- **Data** - 프로그램에 전달할 직렬화된 인수 ``` Instruction: @@ -75,9 +75,9 @@ Instruction: └── data: [encoded transfer amount] ``` -### Multiple Instructions +### 여러 인스트럭션 -Transactions can contain multiple instructions that execute atomically: +트랜잭션은 원자적으로 실행되는 여러 인스트럭션을 포함할 수 있습니다. ```javascript import { transactionBuilder } from '@metaplex-foundation/umi' @@ -91,14 +91,14 @@ const builder = transactionBuilder() await builder.sendAndConfirm(umi) ``` -This atomicity is powerful. If any instruction fails, the entire transaction is reverted. +이 원자성은 강력한 특성입니다. 인스트럭션 하나라도 실패하면 전체 트랜잭션이 되돌려집니다. ## Recent Blockhash -Every transaction requires a **recent blockhash** that: -- Proves the transaction was created recently -- Prevents replay attacks -- Expires after ~60-90 seconds (~150 slots) +모든 트랜잭션에는 다음 역할을 하는 **recent blockhash**가 필요합니다. +- 트랜잭션이 최근에 생성되었음을 증명합니다. +- 재생 공격을 방지합니다. +- 약 60~90초(약 150슬롯) 후 만료됩니다. ```javascript // UMI handles blockhash automatically when sending transactions. @@ -106,13 +106,13 @@ Every transaction requires a **recent blockhash** that: const { blockhash, lastValidBlockHeight } = await umi.rpc.getLatestBlockhash() ``` -{% callout title="Blockhash Expiration" type="warning" %} -If your transaction isn't confirmed before the blockhash expires, it will be dropped. For long-running operations, fetch a fresh blockhash before sending. +{% callout title="Blockhash 만료" type="warning" %} +blockhash가 만료되기 전에 트랜잭션이 확인되지 않으면 해당 트랜잭션은 폐기됩니다. 오래 실행되는 작업에서는 전송 전에 새로운 blockhash를 가져오세요. {% /callout %} -## Signing Transactions +## 트랜잭션 서명 -Transactions must be signed by all accounts marked as `isSigner`: +트랜잭션은 `isSigner`로 표시된 모든 계정의 서명을 받아야 합니다. ```javascript // UMI signs automatically with the identity signer when sending. @@ -130,9 +130,9 @@ const encoded = base64.deserialize(serialized)[0] // ... send encoded string to another party for additional signing ... ``` -## Sending Transactions +## 트랜잭션 전송 -### Basic Send +### 기본 전송 ```javascript // Send and wait for confirmation (recommended) @@ -142,7 +142,7 @@ const result = await myBuilder.sendAndConfirm(umi) const signature = await myBuilder.send(umi) ``` -### Send with Options +### 옵션을 사용한 전송 ```javascript const result = await myBuilder.sendAndConfirm(umi, { @@ -151,17 +151,17 @@ const result = await myBuilder.sendAndConfirm(umi, { }) ``` -## Transaction Confirmation +## 트랜잭션 확인 -Solana has multiple **commitment levels** indicating transaction finality: +Solana에는 트랜잭션 최종성을 나타내는 여러 **commitment 레벨**이 있습니다. -| Commitment | Description | Use Case | +| Commitment | 설명 | 사용 사례 | |------------|-------------|----------| -| `processed` | Transaction received by leader | Real-time updates | -| `confirmed` | Voted on by supermajority | Most applications | -| `finalized` | 31+ blocks deep, irreversible | Financial operations | +| `processed` | 리더가 트랜잭션을 수신함 | 실시간 업데이트 | +| `confirmed` | 초다수의 투표를 받음 | 대부분의 애플리케이션 | +| `finalized` | 31개 이상의 블록 깊이로 되돌릴 수 없음 | 금융 작업 | -### Checking Confirmation +### 확인 상태 조회 ```javascript // sendAndConfirm waits for confirmation automatically. @@ -169,7 +169,7 @@ Solana has multiple **commitment levels** indicating transaction finality: const result = await umi.rpc.getSignatureStatuses([signature]) ``` -### Commitment in Practice +### 실제 commitment 사용 ```javascript // For most operations, 'confirmed' is the right default @@ -183,24 +183,38 @@ const result = await myBuilder.sendAndConfirm(umi, { }) ``` -## Versioned Transactions +## 버전 트랜잭션 -Solana currently supports two transaction formats: +Solana는 세 가지 트랜잭션 형식을 지원합니다. -### Legacy Transactions -- Original format -- Limited to 35 accounts -- Simpler structure +### 레거시 트랜잭션 -### Versioned Transactions (v0) -- Support **Address Lookup Tables** (ALTs) -- Can reference up to 256 accounts -- Required for complex DeFi operations +레거시 트랜잭션은 Address Lookup Tables가 없는 Solana의 원래 트랜잭션 형식을 사용합니다. + +- 원래 형식 +- 계정 35개로 제한 +- 더 단순한 구조 + +### V0 트랜잭션 + +V0 트랜잭션은 더 많은 계정이 필요한 트랜잭션을 위해 Address Lookup Table 지원을 추가합니다. + +- **Address Lookup Tables**(ALT) 지원 +- 최대 256개 계정 참조 가능 +- 복잡한 DeFi 작업에 필요 + +### V1 트랜잭션 + +V1 트랜잭션은 트랜잭션 크기 제한을 늘리고 컴퓨트 구성을 메시지에 저장합니다. + +- 최대 4,096바이트의 트랜잭션 지원 +- 컴퓨트 예산 구성을 트랜잭션 메시지에 저장 +- Address Lookup Tables를 지원하지 않음 ```javascript -// UMI uses V0 transactions by default +// Umi uses V0 transactions by default. Opt in to V1 explicitly. const result = await myBuilder - .useV0() // Explicit, but this is already the default + .useV1() .sendAndConfirm(umi) // To use legacy transactions instead @@ -217,40 +231,44 @@ const [lutBuilder, lut] = createLut(umi, { }) await lutBuilder.sendAndConfirm(umi) -// Use the lookup table in your transaction -await myBuilder.setAddressLookupTables([lut]).sendAndConfirm(umi) +// Address Lookup Tables require V0. +await myBuilder + .useV0() + .setAddressLookupTables([lut]) + .sendAndConfirm(umi) ``` -{% callout title="When to Use Versioned Transactions" %} -Use versioned transactions when: -- Your transaction involves many accounts (>35) -- You're interacting with DeFi protocols that require ALTs -- You want to reduce transaction size +{% callout title="트랜잭션 버전 선택" %} +- 지갑이 트랜잭션 버전 `1`을 지원하고 트랜잭션이 1,232바이트보다 클 때 V1을 사용하세요. +- 트랜잭션에 Address Lookup Table이 필요하면 V0을 사용하세요. +- 호환성을 위해 원래 형식이 필요한 경우에만 레거시 트랜잭션을 사용하세요. -For simple operations (transfers, basic mints), legacy transactions work fine. +Umi는 이전 버전과의 호환성을 위해 V0을 기본값으로 사용합니다. 애플리케이션 전체의 기본값을 변경하기 전에 [V0에서 V1 트랜잭션으로 마이그레이션](/dev-tools/umi/guides/migrate-to-transaction-v1)을 참조하세요. {% /callout %} -## Transaction Size Limits +## 트랜잭션 크기 제한 -Solana transactions have strict size limits: +Solana 트랜잭션에는 엄격한 크기 제한이 있습니다. -| Limit | Value | +| 제한 | 값 | |-------|-------| -| Maximum transaction size | 1232 bytes | -| Maximum accounts | 35 (legacy) / 256 (versioned with ALTs) | -| Maximum instructions | Limited by size | +| 레거시 및 V0 트랜잭션 크기 | 1,232바이트 | +| V1 트랜잭션 크기 | 4,096바이트 | +| Address Lookup Tables | V0에서만 지원 | +| 최대 인스트럭션 수 | 크기에 따라 제한 | -### Dealing with Size Limits +### 크기 제한에 대처하는 방법 -If your transaction is too large: +트랜잭션이 너무 크면 다음 방법을 사용하세요. -1. **Use Address Lookup Tables** - Compress account references -2. **Split into multiple transactions** - Execute sequentially -3. **Optimize instruction data** - Minimize serialized data +1. **V1 사용** - Address Lookup Table이 필요하지 않을 때 크기 제한을 4,096바이트로 늘립니다. +2. **V0에서 Address Lookup Tables 사용** - 계정 참조를 압축합니다. +3. **여러 트랜잭션으로 분할** - 순차적으로 실행합니다. +4. **인스트럭션 데이터 최적화** - 직렬화된 데이터를 최소화합니다. -## Simulation +## 시뮬레이션 -Before sending, simulate transactions to catch errors: +전송 전에 트랜잭션을 시뮬레이션하여 오류를 발견하세요. ```javascript // Build the transaction without sending @@ -265,27 +283,27 @@ const simulation = await umi.rpc.simulateTransaction(tx, { console.log('Simulation result:', simulation) ``` -Simulation helps you: -- Catch errors before paying fees -- Estimate compute units -- Debug program logic +시뮬레이션은 다음 작업에 도움이 됩니다. +- 수수료를 지불하기 전에 오류 발견 +- 컴퓨트 유닛 추정 +- 프로그램 로직 디버깅 -## Common Transaction Errors +## 일반적인 트랜잭션 오류 ### "Blockhash not found" -**Cause**: The blockhash expired before confirmation. +**원인**: 확인 전에 blockhash가 만료되었습니다. -**Solutions**: -1. Retry with a fresh blockhash (UMI fetches a new blockhash automatically on each send) -2. Use `'finalized'` commitment for blockhash when network is congested -3. Implement retry logic in your application +**해결 방법**: +1. 새로운 blockhash로 재시도합니다(UMI는 전송할 때마다 새로운 blockhash를 자동으로 가져옵니다). +2. 네트워크가 혼잡할 때 blockhash에 `'finalized'` commitment를 사용합니다. +3. 애플리케이션에 재시도 로직을 구현합니다. ### "Insufficient funds" -**Cause**: Account doesn't have enough SOL for transaction fees + rent. +**원인**: 계정에 트랜잭션 수수료와 rent를 지불할 SOL이 충분하지 않습니다. -**Solution**: Ensure the fee payer has sufficient balance: +**해결 방법**: 수수료 지불자에게 충분한 잔액이 있는지 확인하세요. ```bash solana balance solana airdrop 1 # On devnet @@ -293,23 +311,23 @@ solana airdrop 1 # On devnet ### "Transaction simulation failed" -**Cause**: Program logic error. +**원인**: 프로그램 로직 오류입니다. -**Solution**: Check simulation logs on an explorer (see [Using Solana Explorers](/solana/using-solana-explorers)), or simulate the transaction before sending to inspect the error output. +**해결 방법**: 익스플로러에서 시뮬레이션 로그를 확인하거나([Solana 익스플로러 사용](/solana/using-solana-explorers) 참조), 트랜잭션을 전송하기 전에 시뮬레이션하여 오류 출력을 살펴보세요. ### "Account not found" -**Cause**: An account in the transaction doesn't exist. +**원인**: 트랜잭션의 계정이 존재하지 않습니다. -**Solution**: Create the account first or check addresses. +**해결 방법**: 먼저 계정을 생성하거나 주소를 확인하세요. ### "Invalid account owner" -**Cause**: Account is owned by a different program than expected. +**원인**: 예상한 프로그램이 아닌 다른 프로그램이 계정을 소유하고 있습니다. -**Solution**: Verify account ownership matches the program you're calling. +**해결 방법**: 계정 소유권이 호출하는 프로그램과 일치하는지 확인하세요. -## Practical Example: Complete Flow +## 실전 예시: 전체 흐름 ```javascript import { createUmi } from '@metaplex-foundation/umi-bundle-defaults' @@ -337,26 +355,26 @@ console.log('Transaction confirmed:', signature) console.log(`Explorer: https://explorer.solana.com/tx/${signature}?cluster=devnet`) ``` -## Next Steps +## 다음 단계 -- [Compute units and priority fees](/solana/compute-units-and-priority-fees) - Optimize transaction landing -- [Working with devnet and testnet](/solana/working-with-devnet-and-testnet) - Test your transactions -- [Diagnose transaction errors](/solana/general/how-to-diagnose-solana-transaction-errors) - Debug failed transactions +- [컴퓨트 유닛과 우선순위 수수료](/solana/compute-units-and-priority-fees) - 트랜잭션 랜딩 최적화 +- [devnet 및 testnet 사용](/solana/working-with-devnet-and-testnet) - 트랜잭션 테스트 +- [트랜잭션 오류 진단](/solana/general/how-to-diagnose-solana-transaction-errors) - 실패한 트랜잭션 디버깅 ## FAQ -### How long do I have to confirm a transaction? +### 트랜잭션을 확인하는 데 주어진 시간은 얼마인가요? -A transaction's blockhash is valid for approximately 60-90 seconds (~150 slots). After that, the transaction will be dropped if not confirmed. +트랜잭션의 blockhash는 약 60~90초(약 150슬롯) 동안 유효합니다. 이 시간이 지나도록 확인되지 않으면 트랜잭션이 폐기됩니다. -### Can I cancel a transaction? +### 트랜잭션을 취소할 수 있나요? -No, once submitted, you cannot cancel a transaction. However, if it hasn't been confirmed, you can submit a new transaction with the same nonce (using durable nonces) to effectively "replace" it. +아니요. 한 번 제출된 트랜잭션은 취소할 수 없습니다. 다만 아직 확인되지 않았다면 동일한 nonce를 사용하는 새 트랜잭션을 제출하여(durable nonce 사용) 사실상 기존 트랜잭션을 "대체"할 수 있습니다. -### What's the difference between "processed" and "confirmed"? +### "processed"와 "confirmed"의 차이점은 무엇인가요? -"Processed" means a validator received it. "Confirmed" means a supermajority (66%+) of validators voted on the block containing it. Always use "confirmed" or "finalized" for important operations. +"processed"는 검증자가 트랜잭션을 수신했다는 의미입니다. "confirmed"는 검증자 초다수(66% 이상)가 해당 트랜잭션을 포함하는 블록에 투표했다는 의미입니다. 중요한 작업에는 항상 "confirmed" 또는 "finalized"를 사용하세요. -### Why did my transaction fail after simulation succeeded? +### 시뮬레이션은 성공했는데 트랜잭션이 실패한 이유는 무엇인가요? -State can change between simulation and execution. Another transaction may have modified the accounts. This is common in competitive scenarios like NFT mints. +시뮬레이션과 실행 사이에 상태가 변경될 수 있습니다. 다른 트랜잭션이 계정을 수정했을 수 있습니다. NFT 민팅과 같은 경쟁이 치열한 상황에서 흔히 발생합니다. diff --git a/src/pages/zh/dev-tools/umi/guides/migrate-to-transaction-v1.md b/src/pages/zh/dev-tools/umi/guides/migrate-to-transaction-v1.md new file mode 100644 index 000000000..8f4f4df50 --- /dev/null +++ b/src/pages/zh/dev-tools/umi/guides/migrate-to-transaction-v1.md @@ -0,0 +1,268 @@ +--- +title: 从 V0 迁移到 V1 交易 +metaTitle: 从 V0 迁移到 V1 交易 | Umi +description: 将 Umi 交易构建器和直接创建交易的方式从 Solana V0 交易迁移到 V1 交易,包括计算预算、优先费和钱包兼容性。 +keywords: + - Umi transaction v1 + - Solana transaction v1 + - Umi v0 migration + - TransactionV1Config + - useV1 + - setTransactionConfig + - SIMD-0385 +about: + - Umi + - Solana Transaction V1 + - Transaction Migration +proficiencyLevel: Intermediate +programmingLanguage: + - JavaScript + - TypeScript +created: '09-21-2026' +updated: '09-21-2026' +howToSteps: + - 将 Umi 软件包升级到 1.6.0 或更高版本,并将 web3.js 升级到 1.99.0 或更高版本 + - 为单个交易构建器选择 V1,或将 V1 设为应用默认版本 + - 使用 TransactionV1Config 取代 Compute Budget 指令 + - 将需要 Address Lookup Tables 的交易保留在 V0 + - 在签名前确认每个已连接的钱包都支持 V1 交易 +howToTools: + - Umi 1.6.0 or later + - web3.js 1.99.0 or later + - Solana RPC +faqs: + - q: Umi 默认使用 V1 交易吗? + a: 不会。为了向后兼容,Umi 1.6.0 仍以 V0 为默认版本。请在交易构建器上调用 useV1,或在创建 Umi 时将 defaultTransactionVersion 设置为 1。 + - q: Umi V1 交易可以使用地址查找表吗? + a: 不可以。V1 交易不支持地址查找表。任何需要地址查找表的交易都应继续使用 V0。 + - q: V1 交易可以包含 Compute Budget 程序指令吗? + a: 不可以。Umi 会拒绝包含 Compute Budget 指令的 V1 交易构建器。请使用 setTransactionConfig 设置计算单元上限、优先费总额、已加载账户数据大小上限或堆大小。 + - q: V1 交易优先费是按每个计算单元计价吗? + a: 不是。TransactionV1Config.priorityFee 是以 SolAmount 表示的优先费总额。将 micro-lamport 单价乘以计算单元上限,再除以 1,000,000,并向上取整为 lamport。 + - q: 所有 Solana 钱包都支持 V1 交易吗? + a: 不是。Umi 可以为钱包适配器序列化 V1 交易,但连接的钱包必须接受并签署版本为 1 的交易。在将 V1 设为应用级默认版本前,请先检查钱包支持情况。 +--- + +将 Umi 应用从 V0 迁移到 [V1 交易](https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0385-transaction-v1.md),以使用更大的交易,并直接在交易消息中配置计算预算。 {% .lead %} + +{% callout title="您将迁移的内容" %} +本指南将 Umi V0 交易构建器转换为 V1,用 `TransactionV1Config` 取代 Compute Budget 指令,在全局配置 V1,并识别必须保留在 V0 上的交易。 +{% /callout %} + +## 总结 + +Umi 1.6.0 通过 `useV1()`、`defaultTransactionVersion: 1` 和直接交易输入中的 `version: 1` 提供可选的 V1 交易支持。 + +- V1 将序列化交易大小上限从 1,232 字节提高到 4,096 字节。 +- V1 在 `TransactionV1Config` 中存储计算上限和优先费总额。 +- V1 不支持 Address Lookup Tables 或 Compute Budget 指令。 +- Umi 仍默认使用 V0,且连接的钱包必须支持 V1。 + +## 快速开始 + +在交易构建器上选择 V1,并使用 `setTransactionConfig` 取代 Compute Budget 指令。 + +1. 升级到 Umi 1.6.0 或更高版本,并升级到 `@solana/web3.js` 1.99.0 或更高版本。 +2. 向交易构建器添加 `.useV1()`。 +3. 移除 `setComputeUnitLimit` 和 `setComputeUnitPrice` 指令。 +4. 添加 `.setTransactionConfig({ computeUnitLimit, priorityFee })`。 +5. 使用应用支持的每一种钱包测试 V1 签名。 + +**跳转到:** [先决条件](#先决条件) · [V0 与 V1 的差异](#v0-与-v1-交易的差异) · [构建器迁移](#将交易构建器迁移到-v1) · [应用默认版本](#将-v1-设为应用默认版本) · [直接创建](#将直接创建交易迁移到-v1) · [Address Lookup Tables](#将使用-address-lookup-table-的交易保留在-v0) · [常见错误](#常见的-v1-迁移错误) · [常见问题](#常见问题) + +## 先决条件 + +迁移到 V1 需要兼容的 Umi、Web3.js、RPC 和钱包版本。 + +| 组件 | 要求 | +|-----------|-------------| +| Umi 软件包 | 1.6.0 或更高版本 | +| `@solana/web3.js` | 1.99.0 或更高版本 | +| Solana 集群 | V1 已在 mainnet-beta、devnet 和 testnet 上启用 | +| 钱包 | 必须接受并签署版本为 `1` 的交易 | + +{% callout type="warning" %} +在每条已连接钱包的流程都支持交易版本 `1` 之前,请勿在全局启用 V1。Umi 可以为钱包适配器序列化交易,但无法让不兼容的钱包签署该交易。 +{% /callout %} + +## V0 与 V1 交易的差异 + +V1 提高了交易大小上限,但不支持 V0 的 Address Lookup Tables 或 Compute Budget 指令。 + +| 功能 | V0 | V1 | +|------------|----------------|----------------| +| 序列化大小上限 | 1,232 字节 | 4,096 字节 | +| 地址查找表 | 支持 | 不支持 | +| 计算单元上限 | Compute Budget 指令 | `transactionConfig.computeUnitLimit` | +| 优先费 | 每个计算单元的 micro-lamport 数量 | `transactionConfig.priorityFee` 中的 `SolAmount` 总额 | +| Umi 1.6.0 中的默认版本 | 是 | 否,必须主动选择 | +| 构建器选择器 | `useV0()` | `useV1()` | + +当交易超过 V0 大小上限但不依赖 Address Lookup Table 时,V1 最为实用。 + +## 将交易构建器迁移到 V1 + +要将 V0 交易构建器迁移到 V1,需要用 `useV1()` 和 `setTransactionConfig()` 取代 Compute Budget 指令。 + +### 迁移前的 V0 交易构建器 + +V0 交易构建器通过指令表达计算单元上限和价格。 + +```typescript {% title="transaction-v0.ts" %} +import { transactionBuilder } from '@metaplex-foundation/umi' +import { + setComputeUnitLimit, + setComputeUnitPrice, + transferSol, +} from '@metaplex-foundation/mpl-toolbox' + +await transactionBuilder() + .add(setComputeUnitLimit(umi, { units: 600_000 })) + .add(setComputeUnitPrice(umi, { microLamports: 1_000 })) + .add(transferSol(umi, transferArgs)) + .sendAndConfirm(umi) +``` + +### 迁移后的 V1 交易构建器 + +V1 交易构建器在交易消息中表达计算单元上限和优先费总额。 + +```typescript {% title="transaction-v1.ts" %} +import { lamports, transactionBuilder } from '@metaplex-foundation/umi' +import { transferSol } from '@metaplex-foundation/mpl-toolbox' + +await transactionBuilder() + .add(transferSol(umi, transferArgs)) + .useV1() + .setTransactionConfig({ + computeUnitLimit: 600_000, + priorityFee: lamports(600), + }) + .sendAndConfirm(umi) +``` + +优先费总额 `600` lamport 等于 `600,000 × 1,000 ÷ 1,000,000`。如果转换结果不是整数 lamport,请向上取整。 + +{% callout type="note" %} +`setTransactionConfig()` 会替换完整配置。请在同一次调用中包含所有自定义 V1 设置,而不要重复调用来分别设置各字段。 +{% /callout %} + +## 将 V1 设为应用默认版本 + +设置 `defaultTransactionVersion: 1` 后,除非构建器明确选择其他版本,否则所有交易构建器都将使用 V1。 + +```typescript {% title="umi.ts" %} +import { createUmi } from '@metaplex-foundation/umi-bundle-defaults' + +const umi = createUmi('https://api.mainnet-beta.solana.com', { + defaultTransactionVersion: 1, +}) +``` + +此选项也会影响 Metaplex 程序库返回的构建器。调用 `useV0()` 的构建器仍会覆盖应用默认版本。 + +直接安装交易工厂的应用可以改为配置插件: + +```typescript {% title="umi-with-custom-plugins.ts" %} +import { web3JsTransactionFactory } from '@metaplex-foundation/umi-transaction-factory-web3js' + +umi.use(web3JsTransactionFactory({ defaultTransactionVersion: 1 })) +``` + +## 将直接创建交易迁移到 V1 + +直接调用 `umi.transactions.create()` 时,必须设置 `version: 1`,并提供明确的非零运行时上限。 + +```typescript {% title="create-transaction-v1.ts" %} +const transaction = umi.transactions.create({ + version: 1, + blockhash: (await umi.rpc.getLatestBlockhash()).blockhash, + instructions: [myInstruction], + payer: umi.payer.publicKey, + transactionConfig: { + computeUnitLimit: 200_000, + loadedAccountsDataSizeLimit: 64 * 1024 * 1024, + }, +}) +``` + +对于省略的计算上限和已加载账户数据上限,`TransactionBuilder` 会提供与旧版等效的默认值。低级 `create()` 方法不会提供默认值;运行时会将省略的上限视为零。 + +## 配置 V1 交易上限 + +`TransactionV1Config` 控制计算量、账户数据、堆大小和优先费总额。 + +| 字段 | 含义 | 有效范围或行为 | +|-------|---------|-------------------------| +| `computeUnitLimit` | 最大计算单元数 | `0` 到 `1,400,000` 之间的整数 | +| `priorityFee` | 优先费总额 | `SolAmount`,通常使用 `lamports(...)` 创建 | +| `loadedAccountsDataSizeLimit` | 已加载账户数据的最大大小 | 最大 64 MiB | +| `heapSize` | 程序堆帧大小 | 32,768 到 262,144 字节,增量为 1,024 字节 | + +省略这些字段时,构建器默认将 `computeUnitLimit` 设为 `min(200,000 × 指令数量, 1,400,000)`,并将 `loadedAccountsDataSizeLimit` 设为 64 MiB。 + +## 将使用 Address Lookup Table 的交易保留在 V0 + +需要 [Address Lookup Tables](/dev-tools/umi/toolbox/address-lookup-table) 的交易必须保留在 V0。 + +```typescript {% title="transaction-v0-with-lookup-table.ts" %} +const builder = transactionBuilder() + .add(myInstruction) + .useV0() + .setAddressLookupTables([myLookupTable]) +``` + +请勿仅为强制交易使用 V1 而移除 Address Lookup Table。应比较编译后的账户列表和序列化大小,然后使用满足交易要求的格式。 + +## 更新自定义 Umi 集成 + +升级到 Umi 1.6.0 时,自定义交易工厂和穷举式版本处理必须添加 V1 支持。 + +- 在自定义 `TransactionFactoryInterface` 实现上实现 `getDefaultVersion()`。 +- 对穷举切换 `TransactionVersion` 的代码添加 `1` 分支。 +- 对直接创建的 V0 `TransactionInput` 对象添加 `version: 0`,因为现在必须提供 V0 版本字段。 +- 读取交易时检查 `transaction.message.version`;V1 消息包含 `transactionConfig`。 + +Umi 的 RPC 集成会请求 `maxSupportedTransactionVersion: 1`,因此 `umi.rpc.getTransaction()` 可以获取 V1 交易。 + +## 常见的 V1 迁移错误 + +Umi 会在发送交易前拒绝不兼容的构建器组合。 + +| 错误 | 原因 | 修复方法 | +|-------|-------|-----| +| `V1 transactions ignore ComputeBudget instructions. Set the compute budget with setTransactionConfig instead.` | V1 交易构建器包含 `setComputeUnitLimit`、`setComputeUnitPrice` 或其他 Compute Budget 指令 | 移除该指令并使用 `setTransactionConfig()` | +| `Address lookup tables are not supported by V1 transactions.` | V1 交易构建器包含一个或多个 Address Lookup Tables | 将构建器保留在 V0,或移除对查找表的需求 | +| `Transaction configs are only supported by V1 transactions.` | 旧版或 V0 交易构建器调用 `setTransactionConfig()` | 调用 `useV1()`,或在 V0 上使用 Compute Budget 指令 | +| 钱包拒绝交易或无法反序列化交易 | 钱包不支持交易版本 `1` | 在钱包添加 V1 支持前,使该钱包流程继续使用 V0 | +| 直接创建交易后因计算预算不足而失败 | `create()` 未收到 `computeUnitLimit` | 设置非零的 `transactionConfig.computeUnitLimit` | + +## 注意事项 + +- 在 Umi 1.6.0 中,V1 为可选版本;为了向后兼容,默认版本仍为 V0。 +- V1 于 2026 年 9 月 15 日在 Solana mainnet-beta 的 epoch 1035 中启用。 +- 发送和模拟使用 base64 编码,支持大于 1,232 字节的 V1 交易。 +- Umi 会在序列化前验证计算单元上限和堆大小。 +- 实现与兼容性详情记录在 [metaplex-foundation/umi#216](https://github.com/metaplex-foundation/umi/pull/216) 中。 + +## 常见问题 + +### Umi 默认使用 V1 交易吗? + +为了向后兼容,Umi 1.6.0 仍以 V0 为默认版本。请在交易构建器上调用 `useV1()`,或在创建 Umi 时设置 `defaultTransactionVersion: 1`。 + +### Umi V1 交易可以使用 Address Lookup Table 吗? + +V1 交易不支持 Address Lookup Tables。任何需要 Address Lookup Table 的交易都应继续使用 V0。 + +### V1 交易可以包含 Compute Budget 程序指令吗? + +Umi 会拒绝包含 Compute Budget 指令的 V1 交易构建器。请使用 `setTransactionConfig()` 设置计算单元上限、优先费总额、已加载账户数据大小上限或堆大小。 + +### V1 交易优先费是按每个计算单元计价吗? + +`TransactionV1Config.priorityFee` 是以 `SolAmount` 表示的优先费总额,而不是每个计算单元的价格。将 micro-lamport 单价乘以计算单元上限,再除以 1,000,000,并向上取整为 lamport。 + +### 所有 Solana 钱包都支持 V1 交易吗? + +交易版本 `1` 尚未得到所有钱包的支持。Umi 可以为钱包适配器序列化 V1 交易,但连接的钱包必须接受并签署该交易。 diff --git a/src/pages/zh/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees.md b/src/pages/zh/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees.md index aec1525d6..3b0e5d46d 100644 --- a/src/pages/zh/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees.md +++ b/src/pages/zh/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees.md @@ -1,55 +1,86 @@ --- title: 使用计算单元(CU)和优先费优化交易落地 metaTitle: Umi - 使用计算单元(CU)和优先费优化交易落地 -description: 学习如何通过计算和设置适当的计算单元(CU)和优先费来优化您的 Solana 交易。 +description: 了解如何通过计算并设置适当的计算单元(CU)和优先费来优化 Solana 交易。 +keywords: + - Umi transaction v1 + - compute units + - priority fees + - transaction optimization +about: + - Umi + - Solana Transaction V1 + - Priority Fees +proficiencyLevel: Intermediate +programmingLanguage: + - JavaScript + - TypeScript created: '12-02-2024' -updated: '12-02-2024' +updated: '09-21-2026' --- -在 Solana 上发送交易时,优化两个关键参数可以显著提高交易的成功率和成本效益: +## 总结 + +Umi V1 交易通过模拟来估算计算消耗,并将计算上限和优先费总额存储在 `TransactionV1Config` 中。 + +- 使用 1,400,000 的计算单元上限进行模拟。 +- 为消耗的计算单元增加安全余量。 +- 估算每个计算单元的市场价格,单位为 micro-lamport。 +- 在调用 `setTransactionConfig()` 前,将估算结果转换为以 lamport 计的费用总额。 + +在 Solana 上发送交易时,优化两个关键参数可以显著提高交易成功率和成本效益。 + +## 快速开始 + +在发送交易前,估算 V1 的计算单元上限和优先费总额。 + +1. 根据交易可写账户近期支付的费用[估算优先费](#优先费)。 +2. 使用 V1 的最大计算单元上限[模拟交易](#计算单元上限)。 +3. 使用 `setTransactionConfig()` [应用估算值](#实现指南)。 +4. [运行完整的 SOL 转账示例](#sol-转账完整示例)。 ## 优先费 -优先费让您可以在本地费用市场中出价,以更快地将交易包含在区块中。当网络拥堵且多个交易竞争修改相同账户时,验证者会优先处理具有更高优先费的交易。 +优先费让您可以在本地费用市场中出价,使交易更快被纳入区块。当网络拥堵且多个交易竞争修改相同账户时,验证者会优先处理优先费更高的交易。 -关于优先费的要点: -- 它们的计算方式为:`compute_unit_limit * compute_unit_price` -- 更高的费用增加更快包含的可能性 -- 根据当前网络竞争情况只支付必要的费用 +优先费的要点: +- 计算公式为:`compute_unit_limit * compute_unit_price` +- 更高的费用会提高交易更快被纳入区块的可能性 +- 应根据当前网络竞争情况,仅支付必要的费用 -## 计算单元限制 +## 计算单元上限 -计算单元(CU)表示您的交易所需的计算资源。虽然交易默认请求许多 CU 作为安全措施,但这通常是低效的: +计算单元(CU)表示交易所需的计算资源。虽然交易默认会请求大量 CU 作为安全措施,但这通常效率不高: -1. 无论实际使用情况如何,您都要为所有请求的 CU 支付优先费 -2. 区块具有有限的 CU 容量 - 请求过多的 CU 会减少每个区块的总交易数 +1. 无论实际使用量如何,都要为所有请求的 CU 支付优先费 +2. 区块的 CU 容量有限,请求过多 CU 会减少每个区块能够容纳的交易总数 -优化 CU 限制的好处: -- 通过只支付所需的 CU 来降低交易成本 -- 通过允许每个区块更多交易来提高网络效率 -- 仍然确保有足够的资源用于执行 +优化 CU 上限的好处: +- 仅为所需的 CU 付费,从而降低交易成本 +- 让每个区块容纳更多交易,从而提高网络效率 +- 同时确保有足够的资源执行交易 -例如,简单的代币转账可能只需要 20,000 CU,而 NFT 铸造可能需要 100,000 CU。适当设置这些限制有助于优化您的成本和整体网络吞吐量。 +例如,简单的代币转账可能只需要 20,000 CU,而 NFT 铸造可能需要 100,000 CU。适当设置这些上限有助于同时优化成本和整体网络吞吐量。 ## 实现指南 -本指南演示如何以编程方式计算最佳值,而不是猜测。 +本指南演示如何通过编程方式计算最佳值,而不是依靠猜测。 {% callout type="warning" %} -代码示例使用 `fetch` 进行 RPC 调用,因为 Umi 尚未实现这些方法。当添加官方支持时,优先使用 Umi 的内置方法。 +代码示例使用 `fetch` 进行 RPC 调用,因为 Umi 尚未实现这些方法。添加官方支持后,请优先使用 Umi 的内置方法。 {% /callout %} ### 计算优先费 -使用优先费时,重要的是要记住,当考虑竞争时,这些费用效果最好。手动添加一个巨大的数字可能导致支付超过所需的费用,而使用太低的数字可能导致在竞争激烈时交易不被包含在区块中。 +使用优先费时,必须考虑竞争情况才能取得最佳效果。手动设置一个很大的数值可能导致支付远超所需的费用,而数值过低则可能在竞争激烈时导致交易无法被纳入区块。 -要获取为我们交易中的账户支付的最后优先费,可以使用 `getRecentPrioritizationFees` RPC 调用。我们使用结果基于前 100 个支付的费用计算平均值。这个数字可以根据您的经验进行调整。 +要获取交易所涉及账户近期支付的优先费,可以使用 `getRecentPrioritizationFees` RPC 调用。我们根据返回结果中最高的 100 笔费用计算平均值。您可以根据实际经验调整这一数值。 -需要以下步骤: -1. 从您的交易中提取可写账户 -2. 查询这些账户最近支付的费用 -3. 根据市场条件计算最优费用 +需要执行以下步骤: +1. 从交易中提取可写账户 +2. 查询这些账户近期支付的费用 +3. 根据市场情况计算最佳费用 -在页面底部,您可以找到一个使用此方法进行 Sol 转账的完整示例。 +页面底部提供了一个使用此方法执行 SOL 转账的完整示例。 {% totem %} {% totem-accordion title="代码片段" %} @@ -63,8 +94,8 @@ export const getPriorityFee = async ( umi: Umi, transaction: TransactionBuilder ): Promise => { - // 步骤 1:获取交易中涉及的唯一可写账户 - // 我们只关心可写账户,因为它们影响优先费 + // Step 1: Get unique writable accounts involved in the transaction + // We only care about writable accounts since they affect priority fees const distinctPublicKeys = new Set(); transaction.items.forEach(item => { @@ -75,7 +106,7 @@ export const getPriorityFee = async ( }); }); - // 步骤 2:从 RPC 查询这些账户的最近优先费 + // Step 2: Query recent prioritization fees for these accounts from the RPC const response = await fetch(umi.rpc.getEndpoint(), { method: "POST", headers: { "Content-Type": "application/json" }, @@ -95,7 +126,7 @@ export const getPriorityFee = async ( result: { prioritizationFee: number; slot: number; }[]; }; - // 步骤 3:计算前 100 个费用的平均值以获得有竞争力的费率 + // Step 3: Calculate average of top 100 fees to get a competitive rate const fees = data.result?.map(entry => entry.prioritizationFee) || []; const topFees = fees.sort((a, b) => b - a).slice(0, 100); const averageFee = topFees.length > 0 ? Math.ceil( @@ -109,12 +140,12 @@ export const getPriorityFee = async ( {% /totem %} ### 计算计算单元 -为了优化交易成本并确保可靠执行,我们可以通过首先模拟交易来计算理想的计算单元限制。这种方法比使用固定值更精确,有助于避免资源的过度分配。 +为了优化交易成本并确保可靠执行,可以先模拟交易,再计算理想的计算单元上限。这种方法比使用固定值更精确,并有助于避免过度分配资源。 -模拟过程的工作原理: -1. 使用最大计算单元(1,400,000)构建交易 -2. 模拟它以测量实际消耗的计算单元 -3. 添加 10% 的安全缓冲区以应对变化 +模拟过程如下: +1. 使用最大计算单元数(1,400,000)构建交易 +2. 模拟交易以测量实际消耗的计算单元 +3. 增加 10% 的安全余量以应对波动 4. 如果模拟失败,则回退到保守的默认值 {% totem %} @@ -122,13 +153,13 @@ export const getPriorityFee = async ( ```js export const getRequiredCU = async ( umi: Umi, - transaction: Transaction // 步骤 1:传入交易 + transaction: Transaction // Step 1: pass the transaction ): Promise => { - // 如果估算失败的默认值 - const DEFAULT_COMPUTE_UNITS = 800_000; // 标准安全值 - const BUFFER_FACTOR = 1.1; // 添加 10% 安全余量 + // Default values if estimation fails + const DEFAULT_COMPUTE_UNITS = 800_000; // Standard safe value + const BUFFER_FACTOR = 1.1; // Add 10% safety margin - // 步骤 2:模拟交易以获取实际需要的计算单元 + // Step 2: Simulate the transaction to get actual compute units needed const response = await fetch(umi.rpc.getEndpoint(), { method: "POST", headers: { "Content-Type": "application/json" }, @@ -154,38 +185,43 @@ export const getRequiredCU = async ( const data = await response.json(); const unitsConsumed = data.result?.value?.unitsConsumed; - // 如果模拟不提供计算单元,则回退到默认值 + // Fallback to default if simulation doesn't provide compute units if (!unitsConsumed) { console.log("Simulation didn't return compute units, using default value"); return DEFAULT_COMPUTE_UNITS; } - // 将安全缓冲区添加到估计的计算单元 - return Math.ceil(unitsConsumed * BUFFER_FACTOR); // 步骤 3:使用缓冲区 + // Add a safety buffer without exceeding the V1 maximum. + const bufferedUnits = Math.ceil(unitsConsumed * BUFFER_FACTOR); + if (bufferedUnits > 1_400_000) { + throw new Error( + `Transaction requires ${bufferedUnits} compute units after buffering, so it cannot fit within the V1 maximum of 1,400,000. Split it into multiple transactions.` + ); + } + return bufferedUnits; // Step 3: use the buffer }; - const withCU = baseTransaction.prepend( - setComputeUnitPrice(umi, { microLamports: priorityFee }) - ).prepend( - setComputeUnitLimit(umi, { units: 1400000 }) - ); + const withCU = baseTransaction + .useV1() + .setTransactionConfig({ computeUnitLimit: 1_400_000 }); - // 步骤 8:计算最优计算单元限制 + // Step 8: Calculate optimal compute unit limit console.log("Estimating required compute units..."); const requiredUnits = await getRequiredCU(umi, withCU.build(umi)); ``` {% /totem-accordion %} {% /totem %} -### Sol 转账完整示例 -按照上面的代码并引入一些样板代码来创建 Umi 实例,可以生成这样的脚本来创建 Sol 转账交易: +### SOL 转账完整示例 +结合上述代码,并添加一些用于创建 Umi 实例的样板代码,可以得到以下创建 SOL 转账交易的脚本: {% totem %} {% totem-accordion title="完整代码示例" %} ```js import { createUmi } from "@metaplex-foundation/umi-bundle-defaults"; import { + lamports, sol, publicKey, Transaction, @@ -196,25 +232,23 @@ import { } from "@metaplex-foundation/umi"; import { transferSol, - setComputeUnitLimit, - setComputeUnitPrice, mplToolbox, } from "@metaplex-foundation/mpl-toolbox"; import { base58, base64 } from "@metaplex-foundation/umi/serializers"; /** - * 根据最近的交易计算最优优先费 - * 这有助于确保我们的交易通过提供适当的费用快速处理 - * @param umi - Umi 实例 - * @param transaction - 要计算费用的交易 - * @returns 以 microLamports 为单位的平均优先费(1 lamport = 0.000000001 SOL) + * Calculates the optimal priority fee based on recent transactions + * This helps ensure our transaction gets processed quickly by offering an appropriate fee + * @param umi - The Umi instance + * @param transaction - The transaction to calculate the fee for + * @returns The average priority fee in microLamports (1 lamport = 0.000000001 SOL) */ export const getPriorityFee = async ( umi: Umi, transaction: TransactionBuilder ): Promise => { - // 获取交易中涉及的唯一可写账户 - // 我们只关心可写账户,因为它们影响优先费 + // Get unique writable accounts involved in the transaction + // We only care about writable accounts since they affect priority fees const distinctPublicKeys = new Set(); transaction.items.forEach(item => { @@ -225,7 +259,7 @@ export const getPriorityFee = async ( }); }); - // 从 RPC 查询这些账户的最近优先费 + // Query recent prioritization fees for these accounts from the RPC const response = await fetch(umi.rpc.getEndpoint(), { method: "POST", headers: { "Content-Type": "application/json" }, @@ -245,7 +279,7 @@ export const getPriorityFee = async ( result: { prioritizationFee: number; slot: number; }[]; }; - // 计算前 100 个费用的平均值以获得有竞争力的费率 + // Calculate average of top 100 fees to get a competitive rate const fees = data.result?.map(entry => entry.prioritizationFee) || []; const topFees = fees.sort((a, b) => b - a).slice(0, 100); const averageFee = topFees.length > 0 ? Math.ceil( @@ -255,21 +289,21 @@ export const getPriorityFee = async ( }; /** - * 估算交易所需的计算单元 - * 这有助于防止计算单元分配错误,同时保持成本效益 - * @param umi - Umi 实例 - * @param transaction - 要估算计算单元的交易 - * @returns 带有 10% 安全缓冲区的估计所需计算单元 + * Estimates the required compute units for a transaction + * This helps prevent compute unit allocation errors while being cost-efficient + * @param umi - The Umi instance + * @param transaction - The transaction to estimate compute units for + * @returns Estimated compute units needed with 10% safety buffer */ export const getRequiredCU = async ( umi: Umi, transaction: Transaction ): Promise => { - // 如果估算失败的默认值 - const DEFAULT_COMPUTE_UNITS = 800_000; // 标准安全值 - const BUFFER_FACTOR = 1.1; // 添加 10% 安全余量 + // Default values if estimation fails + const DEFAULT_COMPUTE_UNITS = 800_000; // Standard safe value + const BUFFER_FACTOR = 1.1; // Add 10% safety margin - // 模拟交易以获取实际需要的计算单元 + // Simulate the transaction to get actual compute units needed const response = await fetch(umi.rpc.getEndpoint(), { method: "POST", headers: { "Content-Type": "application/json" }, @@ -295,38 +329,44 @@ export const getRequiredCU = async ( const data = await response.json(); const unitsConsumed = data.result?.value?.unitsConsumed; - // 如果模拟不提供计算单元,则回退到默认值 + // Fallback to default if simulation doesn't provide compute units if (!unitsConsumed) { console.log("Simulation didn't return compute units, using default value"); return DEFAULT_COMPUTE_UNITS; } - // 将安全缓冲区添加到估计的计算单元 - return Math.ceil(unitsConsumed * BUFFER_FACTOR); + // Add a safety buffer without exceeding the V1 maximum. + const bufferedUnits = Math.ceil(unitsConsumed * BUFFER_FACTOR); + if (bufferedUnits > 1_400_000) { + throw new Error( + `Transaction requires ${bufferedUnits} compute units after buffering, so it cannot fit within the V1 maximum of 1,400,000. Split it into multiple transactions.` + ); + } + return bufferedUnits; }; /** - * 使用示例:演示如何使用优化的计算单元和优先费发送 SOL - * 此示例展示了创建和优化 Solana 交易的完整流程 + * Example usage: Demonstrates how to send SOL with optimized compute units and priority fees + * This example shows a complete flow of creating and optimizing a Solana transaction */ const example = async () => { - // 步骤 1:使用您的 RPC 端点初始化 Umi + // Step 1: Initialize Umi with your RPC endpoint const umi = createUmi("YOUR-ENDPOINT").use(mplToolbox()); - // 步骤 2:设置测试钱包 + // Step 2: Set up a test wallet const signer = generateSigner(umi); umi.use(keypairIdentity(signer)); - // 步骤 3:为钱包充值(仅限 devnet) + // Step 3: Fund the wallet (devnet only) console.log("Requesting airdrop for testing..."); await umi.rpc.airdrop(signer.publicKey, sol(0.001)); - await new Promise(resolve => setTimeout(resolve, 15000)); // 等待空投确认 + await new Promise(resolve => setTimeout(resolve, 15000)); // Wait for airdrop confirmation - // 步骤 4:设置基本转账参数 + // Step 4: Set up the basic transfer parameters const destination = publicKey("BeeryDvghgcKPTUw3N3bdFDFFWhTWdWHnsLuVebgsGSD"); const transferAmount = sol(0.00001); // 0.00001 SOL - // 步骤 5:创建基础交易 + // Step 5: Create the base transaction console.log("Creating base transfer transaction..."); const baseTransaction = await transferSol(umi, { source: signer, @@ -334,38 +374,47 @@ const example = async () => { amount: transferAmount, }).setLatestBlockhash(umi); - // 步骤 6:计算最优优先费 + // Step 6: Calculate optimal priority fee console.log("Calculating optimal priority fee..."); const priorityFee = await getPriorityFee(umi, baseTransaction); - // 步骤 7:创建用于计算单元估算的中间交易 - const withCU = baseTransaction.prepend( - setComputeUnitPrice(umi, { microLamports: priorityFee }) - ).prepend( - setComputeUnitLimit(umi, { units: 1400000 }) - ); + // Step 7: Create intermediate transaction for compute unit estimation + const withCU = baseTransaction + .useV1() + .setTransactionConfig({ computeUnitLimit: 1_400_000 }); - // 步骤 8:计算最优计算单元限制 + // Step 8: Calculate optimal compute unit limit console.log("Estimating required compute units..."); const requiredUnits = await getRequiredCU(umi, withCU.build(umi)); - // 步骤 9:构建最终优化的交易 - const finalTransaction = baseTransaction.prepend( - setComputeUnitPrice(umi, { microLamports: priorityFee }) - ).prepend( - setComputeUnitLimit(umi, { units: requiredUnits }) + // Step 9: Build the final optimized transaction + const totalPriorityFeeLamports = Math.ceil( + (priorityFee * requiredUnits) / 1_000_000 ); - console.log(`Transaction optimized with Priority Fee: ${priorityFee} microLamports and ${requiredUnits} compute units`); + const finalTransaction = baseTransaction + .useV1() + .setTransactionConfig({ + computeUnitLimit: requiredUnits, + priorityFee: lamports(totalPriorityFeeLamports), + }); + console.log(`Transaction optimized with a total priority fee of ${totalPriorityFeeLamports} lamports and ${requiredUnits} compute units`); - // 步骤 10:发送并确认交易 + // Step 10: Send and confirm the transaction console.log("Sending optimized transaction..."); const signature = await finalTransaction.sendAndConfirm(umi); console.log("Transaction confirmed! Signature:", base58.deserialize(signature.signature)[0]); }; -// 运行示例 +// Run the example example().catch(console.error); ``` {% /totem-accordion %} {% /totem %} + +## 注意事项 + +- 本指南适用于 Umi 1.6.0 或更高版本以及 V1 交易。 +- `TransactionV1Config.priorityFee` 是以 lamport 计的总金额,而 `getRecentPrioritizationFees` 返回的是每个计算单元以 micro-lamport 计的价格。 +- V1 交易不支持 Address Lookup Tables 或 Compute Budget 指令。 +- 将现有 V0 交易构建器转换为 V1 时,请参阅[从 V0 迁移到 V1 交易](/dev-tools/umi/guides/migrate-to-transaction-v1)。 diff --git a/src/pages/zh/dev-tools/umi/toolbox/priority-fees-and-compute-managment.md b/src/pages/zh/dev-tools/umi/toolbox/priority-fees-and-compute-managment.md index b8c55d7b8..aa2387181 100644 --- a/src/pages/zh/dev-tools/umi/toolbox/priority-fees-and-compute-managment.md +++ b/src/pages/zh/dev-tools/umi/toolbox/priority-fees-and-compute-managment.md @@ -1,39 +1,81 @@ --- -title: 优先费和计算管理 -metaTitle: 优先费和计算管理 | Toolbox -description: 如何在 Umi 中使用优先费和 Compute Budget 程序。 +title: 优先费与计算管理 +metaTitle: 优先费与计算管理 | Toolbox +description: 为 Umi V1 和 V0 交易配置计算单元上限和优先费。 +keywords: + - Umi priority fees + - Umi compute units + - TransactionV1Config + - Compute Budget Program +about: + - Umi + - Solana Transaction Fees +proficiencyLevel: Intermediate +programmingLanguage: + - JavaScript + - TypeScript +created: '09-04-2024' +updated: '09-21-2026' --- -Compute Budget 程序允许我们设置自定义的计算单元限制和价格。您可以在 [Solana 官方文档](https://docs.solana.com/developing/programming-model/runtime#compute-budget)中阅读有关此程序的更多信息。 +## 总结 -## 设置计算单元限制 +使用 `setTransactionConfig()` 配置 V1 交易的计算单元和优先费。 -此指令允许您为交易设置自定义的计算单元限制。 +- V1 使用 `computeUnitLimit` 和优先费总额 `priorityFee`。 +- Umi V1 交易构建器会拒绝 Compute Budget 程序指令。 +- V0 使用 `setComputeUnitLimit` 和 `setComputeUnitPrice`。 +- 对于以每个计算单元的 micro-lamport 数量表示的优先费估算值,必须先转换为总 lamport 数,才能用于 V1。 -```ts -import { transactionBuilder } from '@metaplex-foundation/umi' -import { setComputeUnitLimit } from '@metaplex-foundation/mpl-toolbox' +Umi V1 交易将计算上限和优先费总额存储在交易消息中,而 V0 交易使用 Compute Budget 程序指令。 + +## 配置 V1 计算单元和优先费 + +V1 交易使用 `setTransactionConfig()` 配置计算单元上限和优先费总额。 + +```ts {% title="V1 compute configuration" %} +import { lamports, transactionBuilder } from '@metaplex-foundation/umi' await transactionBuilder() - .add(setComputeUnitLimit(umi, { units: 600_000 })) // 设置计算单元限制。 - .add(...) // 此处添加任何指令。 + .add(myInstruction) + .useV1() + .setTransactionConfig({ + computeUnitLimit: 600_000, + priorityFee: lamports(600), + }) .sendAndConfirm(umi) ``` -## 设置计算单元价格 / 优先费 +`priorityFee` 是费用总额,而不是每个计算单元的价格。当单价为 1,000 micro-lamport、上限为 600,000 个计算单元时,总额为 `600,000 × 1,000 ÷ 1,000,000 = 600` lamport。 + +{% callout type="warning" %} +请勿向 V1 交易构建器添加 `setComputeUnitLimit` 或 `setComputeUnitPrice` 指令。Umi 会拒绝 V1 交易中的 Compute Budget 指令。 +{% /callout %} + +## 配置 V0 计算单元和优先费 -此指令允许您为交易设置每个计算单元的自定义价格 +V0 交易继续使用 `@metaplex-foundation/mpl-toolbox` 中的 Compute Budget 程序指令。 -```ts +```ts {% title="V0 compute configuration" %} import { transactionBuilder } from '@metaplex-foundation/umi' -import { setComputeUnitPrice } from '@metaplex-foundation/mpl-toolbox' +import { + setComputeUnitLimit, + setComputeUnitPrice, +} from '@metaplex-foundation/mpl-toolbox' await transactionBuilder() - .add(setComputeUnitPrice(umi, { microLamports: 1 })) // 以 micro-lamports 为单位设置每个计算单元的价格。 - .add(...) // 此处添加任何指令。 + .add(setComputeUnitLimit(umi, { units: 600_000 })) + .add(setComputeUnitPrice(umi, { microLamports: 1_000 })) + .add(myInstruction) + .useV0() .sendAndConfirm(umi) ``` -{% callout title="如何计算单位和 microLamports 的指南" type="note" %} -为了能够为 `microLamports` 和 `units` 选择适当的数字,创建了一个[小指南](/zh/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees),介绍了可用于计算的不同 RPC 调用。 -{% /callout %} +当交易需要 [Address Lookup Table](/dev-tools/umi/toolbox/address-lookup-table),或连接的钱包不支持 V1 交易时,请使用 V0。 + +## 注意事项 + +- 使用 `useV1()` 和 `setTransactionConfig()` 需要 Umi 1.6.0 或更高版本。 +- V1 计算单元上限不能超过 1,400,000。 +- 请参阅[优化交易落地](/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees),了解如何估算计算单元和费用。 +- 请参阅[从 V0 迁移到 V1 交易](/dev-tools/umi/guides/migrate-to-transaction-v1),了解所有兼容性要求。 diff --git a/src/pages/zh/smart-contracts/bubblegum-v2/mint-cnfts.md b/src/pages/zh/smart-contracts/bubblegum-v2/mint-cnfts.md index e9be713da..76de3c726 100644 --- a/src/pages/zh/smart-contracts/bubblegum-v2/mint-cnfts.md +++ b/src/pages/zh/smart-contracts/bubblegum-v2/mint-cnfts.md @@ -145,7 +145,7 @@ await createCollection(umi, { {% /dialect %} {% /dialect-switcher %} -## 从集合继承版税 +## 从集合继承版税 {% #inheriting-royalties-from-the-collection %} 铸造到 MPL-Core 集合时,可以在叶子上存储**哨兵** seller fee basis points 值(`65535`,导出为 `SELLER_FEE_BASIS_POINTS_INHERIT` / `0xffff`),而不是将集合的版税百分比复制到每个 cNFT。DAS 将集合解析后的费率放在 `royalty.basis_points` / `creators` 上供展示,并将叶子哨兵放在 `royalty.basis_points_raw` / `creators_raw` 上(同时 `royalty.inherited: true`),而链上叶子为哈希保留哨兵值。 diff --git a/src/pages/zh/solana/solana-transaction-fundamentals.md b/src/pages/zh/solana/solana-transaction-fundamentals.md index 47d855b2b..8c62b3d88 100644 --- a/src/pages/zh/solana/solana-transaction-fundamentals.md +++ b/src/pages/zh/solana/solana-transaction-fundamentals.md @@ -1,30 +1,30 @@ --- -title: Solana Transaction Fundamentals -metaTitle: Solana Transaction Fundamentals | How Transactions Work -description: Learn how Solana transactions work, including structure, signing, sending, and confirmation. Essential knowledge for building reliable applications. +title: Solana 交易基础 +metaTitle: Solana 交易基础 | 交易的工作原理 +description: 了解 Solana 交易的工作原理,包括交易结构、签名、发送和确认。这是构建可靠应用的必备知识。 # remember to update dates also in /components/products/guides/index.js created: '02-04-2026' -updated: null +updated: '09-21-2026' --- -A comprehensive guide to understanding how Solana transactions work from structure to confirmation. {% .lead %} +全面了解 Solana 交易从结构到确认的工作原理。 {% .lead %} -## What You'll Learn +## 您将学到什么 -- The anatomy of a Solana transaction -- How to sign and send transactions -- Transaction confirmation and finality -- Versioned transactions vs legacy -- Common transaction errors and their meanings +- Solana 交易的组成结构 +- 如何签署和发送交易 +- 交易确认与最终性 +- 版本化交易与旧版交易的区别 +- 常见交易错误及其含义 -## Prerequisites +## 先决条件 -- [Solana CLI installed](/solana/solana-cli-essentials) -- [Understanding Solana accounts](/solana/understanding-solana-accounts) +- [已安装 Solana CLI](/solana/solana-cli-essentials) +- [了解 Solana 账户](/solana/understanding-solana-accounts) -## Transaction Anatomy +## 交易结构 -A Solana transaction consists of several components: +Solana 交易由多个组成部分构成: ``` ┌─────────────────────────────────────────────────────────────┐ @@ -49,22 +49,22 @@ A Solana transaction consists of several components: └─────────────────────────────────────────────────────────────┘ ``` -### Key Components +### 关键组成部分 -| Component | Description | +| 组成部分 | 说明 | |-----------|-------------| -| **Signatures** | Ed25519 signatures from required signers | -| **Recent Blockhash** | A recent block hash (valid for ~60-90 seconds) | -| **Instructions** | The operations to perform | -| **Account Keys** | All accounts involved in the transaction | +| **签名** | 所需签名者提供的 Ed25519 签名 | +| **近期区块哈希** | 近期区块哈希(有效期约为 60-90 秒) | +| **指令** | 要执行的操作 | +| **账户密钥** | 交易涉及的所有账户 | -## Instructions +## 指令 -Instructions are the actual operations in a transaction. Each instruction specifies: +指令是交易中实际执行的操作。每条指令指定: -- **Program ID** - Which program to execute -- **Accounts** - Which accounts the program needs -- **Data** - Serialized arguments for the program +- **程序 ID** - 要执行哪个程序 +- **账户** - 程序需要哪些账户 +- **数据** - 程序参数的序列化数据 ``` Instruction: @@ -75,9 +75,9 @@ Instruction: └── data: [encoded transfer amount] ``` -### Multiple Instructions +### 多条指令 -Transactions can contain multiple instructions that execute atomically: +一笔交易可以包含多条以原子方式执行的指令: ```javascript import { transactionBuilder } from '@metaplex-foundation/umi' @@ -91,14 +91,14 @@ const builder = transactionBuilder() await builder.sendAndConfirm(umi) ``` -This atomicity is powerful. If any instruction fails, the entire transaction is reverted. +这种原子性非常强大。如果任何一条指令失败,整笔交易都会回滚。 -## Recent Blockhash +## 近期区块哈希 -Every transaction requires a **recent blockhash** that: -- Proves the transaction was created recently -- Prevents replay attacks -- Expires after ~60-90 seconds (~150 slots) +每笔交易都需要一个**近期区块哈希**,它可以: +- 证明交易是近期创建的 +- 防止重放攻击 +- 在约 60-90 秒(约 150 个 slot)后过期 ```javascript // UMI handles blockhash automatically when sending transactions. @@ -106,13 +106,13 @@ Every transaction requires a **recent blockhash** that: const { blockhash, lastValidBlockHeight } = await umi.rpc.getLatestBlockhash() ``` -{% callout title="Blockhash Expiration" type="warning" %} -If your transaction isn't confirmed before the blockhash expires, it will be dropped. For long-running operations, fetch a fresh blockhash before sending. +{% callout title="区块哈希过期" type="warning" %} +如果交易在区块哈希过期前仍未确认,它将被丢弃。对于长时间运行的操作,请在发送前获取新的区块哈希。 {% /callout %} -## Signing Transactions +## 签署交易 -Transactions must be signed by all accounts marked as `isSigner`: +交易必须由所有标记为 `isSigner` 的账户签署: ```javascript // UMI signs automatically with the identity signer when sending. @@ -130,9 +130,9 @@ const encoded = base64.deserialize(serialized)[0] // ... send encoded string to another party for additional signing ... ``` -## Sending Transactions +## 发送交易 -### Basic Send +### 基本发送方式 ```javascript // Send and wait for confirmation (recommended) @@ -142,7 +142,7 @@ const result = await myBuilder.sendAndConfirm(umi) const signature = await myBuilder.send(umi) ``` -### Send with Options +### 使用选项发送 ```javascript const result = await myBuilder.sendAndConfirm(umi, { @@ -151,17 +151,17 @@ const result = await myBuilder.sendAndConfirm(umi, { }) ``` -## Transaction Confirmation +## 交易确认 -Solana has multiple **commitment levels** indicating transaction finality: +Solana 使用多个**承诺级别**来表示交易最终性: -| Commitment | Description | Use Case | +| 承诺级别 | 说明 | 使用场景 | |------------|-------------|----------| -| `processed` | Transaction received by leader | Real-time updates | -| `confirmed` | Voted on by supermajority | Most applications | -| `finalized` | 31+ blocks deep, irreversible | Financial operations | +| `processed` | 交易已被 leader 接收 | 实时更新 | +| `confirmed` | 已获绝大多数验证者投票 | 大多数应用 | +| `finalized` | 已有 31 个以上区块在其之后,不可逆转 | 金融操作 | -### Checking Confirmation +### 检查确认状态 ```javascript // sendAndConfirm waits for confirmation automatically. @@ -169,7 +169,7 @@ Solana has multiple **commitment levels** indicating transaction finality: const result = await umi.rpc.getSignatureStatuses([signature]) ``` -### Commitment in Practice +### 实际使用承诺级别 ```javascript // For most operations, 'confirmed' is the right default @@ -183,24 +183,38 @@ const result = await myBuilder.sendAndConfirm(umi, { }) ``` -## Versioned Transactions +## 版本化交易 -Solana currently supports two transaction formats: +Solana 支持三种交易格式: -### Legacy Transactions -- Original format -- Limited to 35 accounts -- Simpler structure +### 旧版交易 -### Versioned Transactions (v0) -- Support **Address Lookup Tables** (ALTs) -- Can reference up to 256 accounts -- Required for complex DeFi operations +旧版交易使用 Solana 最初的交易格式,不包含 Address Lookup Tables。 + +- 原始格式 +- 最多只能包含 35 个账户 +- 结构更简单 + +### V0 交易 + +V0 交易增加了 Address Lookup Table 支持,适用于需要更多账户的交易。 + +- 支持 **Address Lookup Tables**(ALT) +- 最多可引用 256 个账户 +- 复杂 DeFi 操作需要此格式 + +### V1 交易 + +V1 交易提高了交易大小上限,并将计算配置存储在消息中。 + +- 支持最大 4,096 字节的交易 +- 将计算预算配置存储在交易消息中 +- 不支持 Address Lookup Tables ```javascript -// UMI uses V0 transactions by default +// Umi uses V0 transactions by default. Opt in to V1 explicitly. const result = await myBuilder - .useV0() // Explicit, but this is already the default + .useV1() .sendAndConfirm(umi) // To use legacy transactions instead @@ -217,40 +231,44 @@ const [lutBuilder, lut] = createLut(umi, { }) await lutBuilder.sendAndConfirm(umi) -// Use the lookup table in your transaction -await myBuilder.setAddressLookupTables([lut]).sendAndConfirm(umi) +// Address Lookup Tables require V0. +await myBuilder + .useV0() + .setAddressLookupTables([lut]) + .sendAndConfirm(umi) ``` -{% callout title="When to Use Versioned Transactions" %} -Use versioned transactions when: -- Your transaction involves many accounts (>35) -- You're interacting with DeFi protocols that require ALTs -- You want to reduce transaction size +{% callout title="选择交易版本" %} +- 当交易大于 1,232 字节且钱包支持交易版本 `1` 时,请使用 V1。 +- 当交易需要 Address Lookup Table 时,请使用 V0。 +- 仅在兼容性要求使用原始格式时,才使用旧版交易。 -For simple operations (transfers, basic mints), legacy transactions work fine. +为了向后兼容,Umi 默认使用 V0。在更改应用级默认版本前,请参阅[从 V0 迁移到 V1 交易](/dev-tools/umi/guides/migrate-to-transaction-v1)。 {% /callout %} -## Transaction Size Limits +## 交易大小限制 -Solana transactions have strict size limits: +Solana 交易有严格的大小限制: -| Limit | Value | +| 限制 | 值 | |-------|-------| -| Maximum transaction size | 1232 bytes | -| Maximum accounts | 35 (legacy) / 256 (versioned with ALTs) | -| Maximum instructions | Limited by size | +| 旧版和 V0 交易大小 | 1,232 字节 | +| V1 交易大小 | 4,096 字节 | +| Address Lookup Tables | 仅限 V0 | +| 最大指令数 | 受大小限制 | -### Dealing with Size Limits +### 处理大小限制 -If your transaction is too large: +如果交易过大: -1. **Use Address Lookup Tables** - Compress account references -2. **Split into multiple transactions** - Execute sequentially -3. **Optimize instruction data** - Minimize serialized data +1. **使用 V1** - 在不需要 Address Lookup Table 时,将大小上限提高到 4,096 字节 +2. **在 V0 中使用 Address Lookup Tables** - 压缩账户引用 +3. **拆分为多笔交易** - 按顺序执行 +4. **优化指令数据** - 尽量减少序列化数据 -## Simulation +## 模拟 -Before sending, simulate transactions to catch errors: +在发送前模拟交易,以提前发现错误: ```javascript // Build the transaction without sending @@ -265,51 +283,51 @@ const simulation = await umi.rpc.simulateTransaction(tx, { console.log('Simulation result:', simulation) ``` -Simulation helps you: -- Catch errors before paying fees -- Estimate compute units -- Debug program logic +模拟有助于: +- 在支付费用前发现错误 +- 估算计算单元 +- 调试程序逻辑 -## Common Transaction Errors +## 常见交易错误 -### "Blockhash not found" +### “Blockhash not found” -**Cause**: The blockhash expired before confirmation. +**原因**:区块哈希在交易确认前已过期。 -**Solutions**: -1. Retry with a fresh blockhash (UMI fetches a new blockhash automatically on each send) -2. Use `'finalized'` commitment for blockhash when network is congested -3. Implement retry logic in your application +**解决方法**: +1. 使用新的区块哈希重试(UMI 每次发送时会自动获取新的区块哈希) +2. 网络拥堵时,使用 `'finalized'` 承诺级别获取区块哈希 +3. 在应用中实现重试逻辑 -### "Insufficient funds" +### “Insufficient funds” -**Cause**: Account doesn't have enough SOL for transaction fees + rent. +**原因**:账户没有足够的 SOL 支付交易费和租金。 -**Solution**: Ensure the fee payer has sufficient balance: +**解决方法**:确保费用支付者有足够的余额: ```bash solana balance solana airdrop 1 # On devnet ``` -### "Transaction simulation failed" +### “Transaction simulation failed” -**Cause**: Program logic error. +**原因**:程序逻辑错误。 -**Solution**: Check simulation logs on an explorer (see [Using Solana Explorers](/solana/using-solana-explorers)), or simulate the transaction before sending to inspect the error output. +**解决方法**:在区块浏览器中检查模拟日志(请参阅[使用 Solana 区块浏览器](/solana/using-solana-explorers)),或在发送前模拟交易以检查错误输出。 -### "Account not found" +### “Account not found” -**Cause**: An account in the transaction doesn't exist. +**原因**:交易中的某个账户不存在。 -**Solution**: Create the account first or check addresses. +**解决方法**:先创建该账户或检查地址。 -### "Invalid account owner" +### “Invalid account owner” -**Cause**: Account is owned by a different program than expected. +**原因**:账户由与预期不同的程序所有。 -**Solution**: Verify account ownership matches the program you're calling. +**解决方法**:验证账户所有权是否与所调用的程序一致。 -## Practical Example: Complete Flow +## 实践示例:完整流程 ```javascript import { createUmi } from '@metaplex-foundation/umi-bundle-defaults' @@ -337,26 +355,26 @@ console.log('Transaction confirmed:', signature) console.log(`Explorer: https://explorer.solana.com/tx/${signature}?cluster=devnet`) ``` -## Next Steps +## 后续步骤 -- [Compute units and priority fees](/solana/compute-units-and-priority-fees) - Optimize transaction landing -- [Working with devnet and testnet](/solana/working-with-devnet-and-testnet) - Test your transactions -- [Diagnose transaction errors](/solana/general/how-to-diagnose-solana-transaction-errors) - Debug failed transactions +- [计算单元和优先费](/solana/compute-units-and-priority-fees) - 优化交易落地 +- [使用 devnet 和 testnet](/solana/working-with-devnet-and-testnet) - 测试交易 +- [诊断交易错误](/solana/general/how-to-diagnose-solana-transaction-errors) - 调试失败的交易 -## FAQ +## 常见问题 -### How long do I have to confirm a transaction? +### 我有多长时间确认交易? -A transaction's blockhash is valid for approximately 60-90 seconds (~150 slots). After that, the transaction will be dropped if not confirmed. +交易的区块哈希有效期约为 60-90 秒(约 150 个 slot)。如果在此之后仍未确认,交易将被丢弃。 -### Can I cancel a transaction? +### 我可以取消交易吗? -No, once submitted, you cannot cancel a transaction. However, if it hasn't been confirmed, you can submit a new transaction with the same nonce (using durable nonces) to effectively "replace" it. +不可以。交易一旦提交便无法取消。但是,如果交易尚未确认,您可以使用相同的 nonce(通过 durable nonce)提交新交易,从而有效地“替换”原交易。 -### What's the difference between "processed" and "confirmed"? +### “processed”和“confirmed”有什么区别? -"Processed" means a validator received it. "Confirmed" means a supermajority (66%+) of validators voted on the block containing it. Always use "confirmed" or "finalized" for important operations. +“Processed”表示验证者已收到交易。“Confirmed”表示包含该交易的区块已获得绝大多数(66% 以上)验证者投票。对于重要操作,请始终使用“confirmed”或“finalized”。 -### Why did my transaction fail after simulation succeeded? +### 为什么交易模拟成功后仍然失败? -State can change between simulation and execution. Another transaction may have modified the accounts. This is common in competitive scenarios like NFT mints. +状态可能在模拟和执行之间发生变化。另一笔交易可能修改了相关账户。这在 NFT 铸造等竞争激烈的场景中很常见。