Skip to content

Commit 8216d8b

Browse files
committed
copy over solana docs
1 parent bb103fb commit 8216d8b

File tree

4 files changed

+391
-0
lines changed

4 files changed

+391
-0
lines changed

sdk-sidebar.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,17 @@ const sdkSidebar = {
159159
],
160160
solana: [
161161
'solana/index',
162+
{
163+
type: 'category',
164+
label: 'Guides',
165+
collapsible: false,
166+
collapsed: false,
167+
items: [
168+
'solana/connect/guides/use-wallet-adapter',
169+
'solana/connect/guides/send-legacy-transaction',
170+
'solana/connect/guides/send-versioned-transaction',
171+
],
172+
},
162173
],
163174
}
164175

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# Send a legacy transaction
2+
3+
Once a web application is connected to Phantom, it can prompt the user for permission to send transactions on their behalf.
4+
5+
In order to send a transaction, a web application must:
6+
7+
1. Create an unsigned transaction.
8+
2. Have the transaction be signed and submitted to the network by the user's Phantom wallet.
9+
3. Optionally await network confirmation using a Solana JSON RPC connection.
10+
11+
:::info
12+
For more information about the nature of Solana transactions, refer to the [solana-web3.js](https://solana-foundation.github.io/solana-web3.js/) documentation and the [Solana Cookbook](https://solanacookbook.com/core-concepts/transactions.html#transactions).
13+
:::
14+
15+
For a sample Phantom transaction, check out our [sandbox](https://github.com/phantom-labs/sandbox/blob/b57fdd0e65ce4f01290141a01e33d17fd2f539b9/src/App.tsx#L160).
16+
17+
## Sign and send a transaction
18+
19+
Once a transaction is created, the web application may ask the user's Phantom wallet to sign and send the transaction. If accepted, Phantom will sign the transaction with the user's private key and submit it via a Solana JSON RPC connection. By far the **easiest** and most **recommended** way of doing this is by using the `signAndSendTransaction` method on the provider, but it is also possible to do with `request`. In both cases, the call will return a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) for an object containing the `signature`.
20+
21+
### signAndSendTransaction()
22+
23+
```javascript theme={null}
24+
const provider = getProvider(); // see "Detecting the Provider"
25+
const network = "<NETWORK_URL>";
26+
const connection = new Connection(network);
27+
const transaction = new Transaction();
28+
const { signature } = await provider.signAndSendTransaction(transaction);
29+
await connection.getSignatureStatus(signature);
30+
```
31+
32+
### request()
33+
34+
```javascript theme={null}
35+
const provider = getProvider(); // see "Detecting the Provider"
36+
const network = "<NETWORK_URL>";
37+
const connection = new Connection(network);
38+
const transaction = new Transaction();
39+
const { signature } = await provider.request({
40+
method: "signAndSendTransaction",
41+
params: {
42+
message: bs58.encode(transaction.serializeMessage()),
43+
},
44+
});
45+
await connection.getSignatureStatus(signature);
46+
```
47+
48+
You can also specify a `SendOptions` [object](https://solana-foundation.github.io/solana-web3.js/modules.html#SendOptions) as a second argument into `signAndSendTransaction` or as an `options` parameter when using `request`.
49+
50+
For a live demo of `signAndSendTransaction`, refer to [handleSignAndSendTransaction](https://github.com/phantom-labs/sandbox/blob/b57fdd0e65ce4f01290141a01e33d17fd2f539b9/src/App.tsx#L160) in our sandbox.
51+
52+
## Sign and send multiple transactions
53+
54+
It is also possible to sign and send multiple transactions at once. This is exposed through the `signAndSendAllTransactions` method on the provider. This method accepts an array of Solana transactions, and will optionally accept a [SendOptions](https://solana-foundation.github.io/solana-web3.js/types/SendOptions.html) object as a second parameter. If successful, it will return a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) for an object containing the array of string `signatures` and the `publicKey` of the signer.
55+
56+
### signAndSendAllTransactions()
57+
58+
```typescript theme={null}
59+
const provider = getProvider(); // see "Detecting the Provider"
60+
const network = "<NETWORK_URL>";
61+
const connection = new Connection(network);
62+
const transactions = [new Transaction(), new Transaction()];
63+
const { signatures, publicKey } = await provider.signAndSendAllTransactions(transactions);
64+
await connection.getSignatureStatuses(signatures);
65+
```
66+
67+
## Other signing methods
68+
69+
The following methods are also supported, but are not recommended over `signAndSendTransaction`. It is safer for users, and a simpler API for developers, for Phantom to submit the transaction immediately after signing it instead of relying on the application to do so.
70+
71+
:::warning
72+
The following methods are not supported in the [wallet standard](#) implementation and may be removed in a future release. These methods are only available via the [window.solana object](/solana/detecting-the-provider).
73+
:::
74+
75+
## Sign a transaction (without sending)
76+
77+
Once a transaction is created, a web application may ask the user's Phantom wallet to sign the transaction *without* also submitting it to the network. The easiest and most recommended way of doing this is via the `signTransaction` method on the provider, but it is also possible to do via `request`. In both cases, the call will return a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) for the signed transaction. After the transaction has been signed, an application may submit the transaction itself using [sendRawTransaction](https://solana-foundation.github.io/solana-web3.js/classes/Connection.html#sendRawTransaction) in web3.js.
78+
79+
### signTransaction()
80+
81+
```javascript theme={null}
82+
const provider = getProvider();
83+
const network = "<NETWORK_URL>";
84+
const connection = new Connection(network);
85+
const transaction = new Transaction();
86+
const signedTransaction = await provider.signTransaction(transaction);
87+
const signature = await connection.sendRawTransaction(signedTransaction.serialize());
88+
```
89+
90+
### request()
91+
92+
```javascript theme={null}
93+
const provider = getProvider();
94+
const network = "<NETWORK_URL>";
95+
const connection = new Connection(network);
96+
const transaction = new Transaction();
97+
const signedTransaction = await provider.request({
98+
method: "signTransaction",
99+
params: {
100+
message: bs58.encode(transaction.serializeMessage()),
101+
},
102+
});
103+
const signature = await connection.sendRawTransaction(signedTransaction.serialize());
104+
```
105+
106+
For an example of `signTransaction`, refer to [handleSignTransaction](https://github.com/phantom-labs/sandbox/blob/b57fdd0e65ce4f01290141a01e33d17fd2f539b9/src/App.tsx#L187) in our sandbox.
107+
108+
## Sign multiple transactions
109+
110+
For legacy integrations, Phantom supports signing multiple transactions at once without sending them. This is exposed through the `signAllTransactions` method on the provider. This method is **not recommended** for new integrations. Instead, developers should make use of `signAndSendAllTransactions`.
111+
112+
### signAllTransactions()
113+
114+
```javascript theme={null}
115+
const signedTransactions = await provider.signAllTransactions(transactions);
116+
```
117+
118+
### request()
119+
120+
```javascript theme={null}
121+
const message = transactions.map(transaction => {
122+
return bs58.encode(transaction.serializeMessage());
123+
});
124+
const signedTransactions = await provider.request({
125+
method: "signAllTransactions",
126+
params: { message },
127+
});
128+
```
129+
130+
For an example of `signAllTransactions`, refer to [handleSignAllTransactions](https://github.com/phantom-labs/sandbox/blob/b57fdd0e65ce4f01290141a01e33d17fd2f539b9/src/App.tsx#L213) in our sandbox.
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
# Send a versioned transaction
2+
3+
The Solana runtime supports two types of transactions: `legacy` (see [Send a legacy transaction](/solana/sending-a-transaction)) and `v0` (transactions that can include Address Lookup Tables or LUTs).
4+
5+
The goal of `v0` is to increase the maximum size of a transaction, and hence the number of accounts that can fit in a single atomic transaction. With LUTs, developers can now build transactions with a maximum of 256 accounts, as compared to the limit of 35 accounts in legacy transactions that do not utilize LUTs.
6+
7+
:::info
8+
For a dive deep on versioned transactions, LUTs, and how the above changes affect the anatomy of a transaction, see [Versioned Transactions - Anvit Mangal's Blog](https://anvit.hashnode.dev/versioned-transactions).
9+
:::
10+
11+
On this page, we'll go over the following:
12+
13+
1. Building a versioned tansaction.
14+
2. Signing and sending a versioned transaction.
15+
3. Building an Address LUT.
16+
4. Extending an Address LUT.
17+
5. Signing and sending a versioned transaction using a LUT.
18+
19+
## Build a versioned transaction
20+
21+
Versioned transactions are built in a very similar fashion to [legacy transactions](sending-a-transaction). The only difference is that developers should use the `VersionedTransaction` class rather than the `Transaction` class.
22+
23+
The following example shows how to build a simple transfer instruction. Once the transfer instruction is made, a `MessageV0` formatted transaction message is constructed with the transfer instruction. Finally, a new `VersionedTransaction` is created, parsing in the `v0` compatible message.
24+
25+
### createTransactionV0()
26+
27+
```typescript theme={null}
28+
// create array of instructions
29+
const instructions = [
30+
SystemProgram.transfer({
31+
fromPubkey: publicKey,
32+
toPubkey: publicKey,
33+
lamports: 10,
34+
}),
35+
];
36+
37+
// create v0 compatible message
38+
const messageV0 = new TransactionMessage({
39+
payerKey: publicKey,
40+
recentBlockhash: blockhash,
41+
instructions,
42+
}).compileToV0Message();
43+
44+
// make a versioned transaction
45+
const transactionV0 = new VersionedTransaction(messageV0);
46+
```
47+
48+
For a live example of creating a versioned transaction, refer to [createTransferTransactionV0](https://github.com/phantom-labs/sandbox/blob/main/src/utils/createTransferTransactionV0.ts) in our sandbox.
49+
50+
## Sign and send a versioned transaction
51+
52+
Once a Versioned transaction is created, it can be signed and sent via Phantom using the `signAndSendTransaction` method on the provider. The call will return a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) for an object containing the `signature`. This is the same way a legacy transaction is sent via the Phantom provider.
53+
54+
### signAndSendTransaction()
55+
56+
```javascript theme={null}
57+
const provider = getProvider(); // see "Detecting the Provider"
58+
const network = "<NETWORK_URL>";
59+
const connection = new Connection(network);
60+
const versionedTransaction = new VersionedTransaction();
61+
const { signature } = await provider.signAndSendTransaction(versionedTransaction);
62+
await connection.getSignatureStatus(signature);
63+
```
64+
65+
You can also specify a `SendOptions` [object](https://solana-foundation.github.io/solana-web3.js/modules.html#SendOptions) as a second argument into `signAndSendTransaction()` or as an `options` parameter when using `request`.
66+
67+
For a live demo of signing and sending a versioned transaction, refer to [handleSignAndSendTransactionV0](https://github.com/phantom-labs/sandbox/blob/78dc35fe140140a961345a6af30a058e1e19a7aa/src/App.tsx#L191) in our sandbox.
68+
69+
## Build an Address LUT
70+
71+
Address LUTs can be used to load accounts into table-like data structures. These structures can then be referenced to significantly increase the number of accounts that can be loaded in a single transaction.
72+
73+
This lookup method effectively "*compresses*" a 32-byte address into a 1-byte index value. This "*compression*" enables storing up to 256 address in a single LUT for use inside any given transaction.
74+
75+
With the `@solana/web3.js` [createLookupTable](https://solana-foundation.github.io/solana-web3.js/classes/AddressLookupTableProgram.html#createLookupTable) method, developers can construct the instruction needed to create a new LUT, as well as determine its address. Once we have the LUT instruction, we can construct a transaction, sign it, and send it to create a LUT on-chain. Address LUTs can be created with either a `v0` transaction or a `legacy` transaction. However, the Solana runtime can only retrieve and handle the additional addresses within a LUT while using `v0` transactions.
76+
77+
The following is a code snippet that creates a LUT.
78+
79+
### createAddressLookupTable()
80+
81+
```typescript theme={null}
82+
// create an Address Lookup Table
83+
const [lookupTableInst, lookupTableAddress] = AddressLookupTableProgram.createLookupTable({
84+
authority: publicKey,
85+
payer: publicKey,
86+
recentSlot: slot,
87+
});
88+
89+
// To create the Address Lookup Table on chain:
90+
// send the `lookupTableInst` instruction in a transaction
91+
const lookupMessage = new TransactionMessage({
92+
payerKey: publicKey,
93+
recentBlockhash: blockhash,
94+
instructions: [lookupTableInst],
95+
}).compileToV0Message();
96+
97+
const lookupTransaction = new VersionedTransaction(lookupMessage);
98+
const lookupSignature = await signAndSendTransaction(provider, lookupTransaction);
99+
```
100+
101+
For a live demo of creating a LUT, refer to [handleSignAndSendTransactionV0WithLookupTable](https://github.com/phantom-labs/sandbox/blob/78dc35fe140140a961345a6af30a058e1e19a7aa/src/App.tsx#L218) in our sandbox.
102+
103+
## Extend an Address LUT
104+
105+
Once an Address LUT is created, it can then be extended, which means that accounts can be appended to the table. Using the `@solana/web3.js` library, you can create a new `extend` instruction using the [extendLookupTable](https://solana-labs.github.io/solana-web3.js/classes/AddressLookupTableProgram.html#extendLookupTable) method. Once the extend instruction is created, it can be sent in a transaction.
106+
107+
### extendAddressLookupTable()
108+
109+
```typescript theme={null}
110+
// add addresses to the `lookupTableAddress` table via an `extend` instruction
111+
const extendInstruction = AddressLookupTableProgram.extendLookupTable({
112+
payer: publicKey,
113+
authority: publicKey,
114+
lookupTable: lookupTableAddress,
115+
addresses: [
116+
publicKey,
117+
SystemProgram.programId,
118+
// more `publicKey` addresses can be listed here
119+
],
120+
});
121+
122+
// Send this `extendInstruction` in a transaction to the cluster
123+
// to insert the listing of `addresses` into your lookup table with address `lookupTableAddress`
124+
const extensionMessageV0 = new TransactionMessage({
125+
payerKey: publicKey,
126+
recentBlockhash: blockhash,
127+
instructions: [extendInstruction],
128+
}).compileToV0Message();
129+
130+
const extensionTransactionV0 = new VersionedTransaction(extensionMessageV0);
131+
const extensionSignature = await signAndSendTransaction(provider, extensionTransactionV0);
132+
```
133+
134+
For a live demo of extending a LUT, refer to the [handleSignAndSendTransactionV0WithLookupTable](https://github.com/phantom-labs/sandbox/blob/78dc35fe140140a961345a6af30a058e1e19a7aa/src/App.tsx#L218) function in our sandbox.
135+
136+
## Sign and send a versioned transaction using a LUT
137+
138+
Up until now, we have:
139+
140+
1. Learned how to create a `VersionedTransaction`.
141+
2. Created an Address LUT.
142+
3. Extended the Address LUT.
143+
144+
At this point, we are now ready to sign and send a `VersionedTransaction` using an Address LUT.
145+
146+
First, we need to fetch the account of the created Address LUT.
147+
148+
### getAddressLookupTable()
149+
150+
```typescript theme={null}
151+
// get the table from the cluster
152+
const lookupTableAccount = await connection.getAddressLookupTable(lookupTableAddress).then((res) => res.value);
153+
// `lookupTableAccount` will now be a `AddressLookupTableAccount` object
154+
console.log('Table address from cluster:', lookupTableAccount.key.toBase58());
155+
```
156+
157+
We can also parse and read all the addresses currently stores in the fetched Address LUT.
158+
159+
## Parse and read addresses
160+
161+
```typescript theme={null}
162+
// Loop through and parse all the address stored in the table
163+
for (let i = 0; i < lookupTableAccount.state.addresses.length; i++) {
164+
const address = lookupTableAccount.state.addresses[i];
165+
console.log(i, address.toBase58());
166+
}
167+
```
168+
169+
We can now create the instructions array with an arbitrary transfer instruction, just the way we did while creating the `VersionedTransaction` earlier. This `VersionedTransaction` can then be sent using the `signAndSendTransaction()` provider function.
170+
171+
```typescript theme={null}
172+
// create an array with your desired `instructions`
173+
// in this case, just a transfer instruction
174+
const instructions = [
175+
SystemProgram.transfer({
176+
fromPubkey: publicKey,
177+
toPubkey: publicKey,
178+
lamports: minRent,
179+
}),
180+
];
181+
182+
// create v0 compatible message
183+
const messageV0 = new TransactionMessage({
184+
payerKey: publicKey,
185+
recentBlockhash: blockhash,
186+
instructions,
187+
}).compileToV0Message([lookupTableAccount]);
188+
189+
// make a versioned transaction
190+
const transactionV0 = new VersionedTransaction(messageV0);
191+
const signature = await signAndSendTransaction(provider, transactionV0);
192+
```
193+
194+
For a live demo of of signing and sending a versioned transaction using an Address LUT, refer to the [handleSignAndSendTransactionV0WithLookupTable](https://github.com/phantom-labs/sandbox/blob/78dc35fe140140a961345a6af30a058e1e19a7aa/src/App.tsx#L218) in our sandbox.

0 commit comments

Comments
 (0)