@solana/transactions 2.0.0-experimental.eb5fd16 → 2.0.0-experimental.ed41fe2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +276 -5
- package/dist/index.browser.cjs +516 -354
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +503 -352
- package/dist/index.browser.js.map +1 -1
- package/dist/index.native.js +503 -352
- package/dist/index.native.js.map +1 -1
- package/dist/index.node.cjs +516 -354
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +503 -352
- package/dist/index.node.js.map +1 -1
- package/dist/types/accounts.d.ts +3 -3
- package/dist/types/accounts.d.ts.map +1 -0
- package/dist/types/blockhash.d.ts +7 -9
- package/dist/types/blockhash.d.ts.map +1 -0
- package/dist/types/compilable-transaction.d.ts +7 -0
- package/dist/types/compilable-transaction.d.ts.map +1 -0
- package/dist/types/compile-address-table-lookups.d.ts +3 -3
- package/dist/types/compile-address-table-lookups.d.ts.map +1 -0
- package/dist/types/compile-header.d.ts +1 -1
- package/dist/types/compile-header.d.ts.map +1 -0
- package/dist/types/compile-instructions.d.ts +1 -1
- package/dist/types/compile-instructions.d.ts.map +1 -0
- package/dist/types/compile-lifetime-token.d.ts +2 -2
- package/dist/types/compile-lifetime-token.d.ts.map +1 -0
- package/dist/types/compile-static-accounts.d.ts +3 -3
- package/dist/types/compile-static-accounts.d.ts.map +1 -0
- package/dist/types/compile-transaction.d.ts +6 -7
- package/dist/types/compile-transaction.d.ts.map +1 -0
- package/dist/types/create-transaction.d.ts +1 -1
- package/dist/types/create-transaction.d.ts.map +1 -0
- package/dist/types/decompile-transaction.d.ts +13 -0
- package/dist/types/decompile-transaction.d.ts.map +1 -0
- package/dist/types/durable-nonce.d.ts +9 -9
- package/dist/types/durable-nonce.d.ts.map +1 -0
- package/dist/types/fee-payer.d.ts +6 -6
- package/dist/types/fee-payer.d.ts.map +1 -0
- package/dist/types/index.d.ts +13 -9
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/instructions.d.ts +6 -4
- package/dist/types/instructions.d.ts.map +1 -0
- package/dist/types/message.d.ts +6 -10
- package/dist/types/message.d.ts.map +1 -0
- package/dist/types/serializers/address-table-lookup.d.ts +5 -3
- package/dist/types/serializers/address-table-lookup.d.ts.map +1 -0
- package/dist/types/serializers/header.d.ts +5 -3
- package/dist/types/serializers/header.d.ts.map +1 -0
- package/dist/types/serializers/index.d.ts +2 -1
- package/dist/types/serializers/index.d.ts.map +1 -0
- package/dist/types/serializers/instruction.d.ts +5 -3
- package/dist/types/serializers/instruction.d.ts.map +1 -0
- package/dist/types/serializers/message.d.ts +5 -5
- package/dist/types/serializers/message.d.ts.map +1 -0
- package/dist/types/serializers/transaction-version.d.ts +5 -5
- package/dist/types/serializers/transaction-version.d.ts.map +1 -0
- package/dist/types/serializers/transaction.d.ts +9 -5
- package/dist/types/serializers/transaction.d.ts.map +1 -0
- package/dist/types/signatures.d.ts +9 -13
- package/dist/types/signatures.d.ts.map +1 -0
- package/dist/types/types.d.ts +6 -13
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/unsigned-transaction.d.ts +2 -2
- package/dist/types/unsigned-transaction.d.ts.map +1 -0
- package/dist/types/wire-transaction.d.ts +2 -2
- package/dist/types/wire-transaction.d.ts.map +1 -0
- package/package.json +19 -36
- package/dist/index.development.js +0 -1384
- package/dist/index.development.js.map +0 -1
- package/dist/index.production.min.js +0 -25
- package/dist/types/serializers/unimplemented.d.ts +0 -3
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -14,12 +14,283 @@
|
|
|
14
14
|
|
|
15
15
|
# @solana/transactions
|
|
16
16
|
|
|
17
|
-
This package contains types for creating transactions. It can be used standalone, but it is also exported as part of the Solana JavaScript SDK [`@solana/web3.js@experimental`](https://github.com/solana-labs/solana-web3.js/tree/master/packages/library).
|
|
17
|
+
This package contains types and functions for creating transactions. It can be used standalone, but it is also exported as part of the Solana JavaScript SDK [`@solana/web3.js@experimental`](https://github.com/solana-labs/solana-web3.js/tree/master/packages/library).
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
Transactions are built one step at a time using the transform functions offered by this package. To make it more ergonmic to apply consecutive transforms to your transactions, consider using a pipelining helper like the one in `@solana/functional`.
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
```ts
|
|
22
|
+
import { pipe } from '@solana/functional';
|
|
23
|
+
import {
|
|
24
|
+
appendTransactionInstruction,
|
|
25
|
+
setTransactionFeePayer,
|
|
26
|
+
setTransactionLifetimeUsingBlockhash,
|
|
27
|
+
} from '@solana/transactions';
|
|
22
28
|
|
|
23
|
-
|
|
29
|
+
const transferTransaction = pipe(
|
|
30
|
+
createTransaction({ version: 0 }),
|
|
31
|
+
tx => setTransactionFeePayer(myAddress, tx),
|
|
32
|
+
tx => setTransactionLifetimeUsingBlockhash(latestBlockhash, tx),
|
|
33
|
+
tx => appendTransactionInstruction(createTransferInstruction(myAddress, toAddress, amountInLamports), tx),
|
|
34
|
+
);
|
|
35
|
+
```
|
|
24
36
|
|
|
25
|
-
|
|
37
|
+
## Creating transactions
|
|
38
|
+
|
|
39
|
+
### Types
|
|
40
|
+
|
|
41
|
+
#### `TransactionVersion`
|
|
42
|
+
|
|
43
|
+
As Solana transactions acquire more capabilities their version will advance. This type is a union of all possible transaction versions.
|
|
44
|
+
|
|
45
|
+
### Functions
|
|
46
|
+
|
|
47
|
+
#### `createTransaction()`
|
|
48
|
+
|
|
49
|
+
Given a `TransactionVersion` this method will return an empty transaction having the capabilities of that version.
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { createTransaction } from '@solana/transactions';
|
|
53
|
+
|
|
54
|
+
const tx = createTransaction({ version: 0 });
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Setting the fee payer
|
|
58
|
+
|
|
59
|
+
### Types
|
|
60
|
+
|
|
61
|
+
#### `ITransactionWithFeePayer`
|
|
62
|
+
|
|
63
|
+
This type represents a transaction for which a fee payer has been declared. A transaction must conform to this type to be landed on the network.
|
|
64
|
+
|
|
65
|
+
### Functions
|
|
66
|
+
|
|
67
|
+
#### `setTransactionFeePayer()`
|
|
68
|
+
|
|
69
|
+
Given a base58-encoded address of a system account, this method will return a new transaction having the same type as the one supplied plus the `ITransactionWithFeePayer` type.
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { address } from '@solana/addresses';
|
|
73
|
+
import { setTransactionFeePayer } from '@solana/transactions';
|
|
74
|
+
|
|
75
|
+
const myAddress = address('mpngsFd4tmbUfzDYJayjKZwZcaR7aWb2793J6grLsGu');
|
|
76
|
+
const txPaidByMe = setTransactionFeePayer(myAddress, tx);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Defining a transaction's lifetime
|
|
80
|
+
|
|
81
|
+
A signed transaction can be only be landed on the network if certain conditions are met:
|
|
82
|
+
|
|
83
|
+
- It includes the hash of a recent block
|
|
84
|
+
- It includes the value of an unused nonce known to the network
|
|
85
|
+
|
|
86
|
+
These conditions define a transaction's lifetime, after which it can no longer be landed, even if signed.
|
|
87
|
+
|
|
88
|
+
### Types
|
|
89
|
+
|
|
90
|
+
#### `ITransactionWithBlockhashLifetime`
|
|
91
|
+
|
|
92
|
+
This type represents a transaction whose lifetime is defined by the age of the blockhash it includes. Such a transaction can only be landed on the network if the current block height of the network is less than or equal to the value of `ITransactionWithBlockhashLifetime['lifetimeConstraint']['lastValidBlockHeight']`.
|
|
93
|
+
|
|
94
|
+
#### `IDurableNonceTransaction`
|
|
95
|
+
|
|
96
|
+
This type represents a transaction whose lifetime is defined by the value of a nonce it includes. Such a transaction can only be landed on the network if the nonce is known to the network and has not already been used to land a different transaction.
|
|
97
|
+
|
|
98
|
+
#### `Blockhash`
|
|
99
|
+
|
|
100
|
+
This type represents a string that is particularly known to be the base58-encoded value of a block.
|
|
101
|
+
|
|
102
|
+
#### `Nonce`
|
|
103
|
+
|
|
104
|
+
This type represents a string that is particularly known to be the base58-encoded value of a nonce.
|
|
105
|
+
|
|
106
|
+
### Functions
|
|
107
|
+
|
|
108
|
+
#### `setTransactionLifetimeUsingBlockhash()`
|
|
109
|
+
|
|
110
|
+
Given a blockhash and the last block height at which that blockhash is considered usable to land transactions, this method will return a new transaction having the same type as the one supplied plus the `ITransactionWithBlockhashLifetime` type.
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
import { setTransactionLifetimeUsingBlockhash } from '@solana/transactions';
|
|
114
|
+
|
|
115
|
+
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
|
|
116
|
+
const txWithBlockhashLifetime = setTransactionLifetimeUsingBlockhash(latestBlockhash, tx);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
#### `setTransactionLifetimeUsingDurableNonce()`
|
|
120
|
+
|
|
121
|
+
Given a nonce, the account where the value of the nonce is stored, and the address of the account authorized to consume that nonce, this method will return a new transaction having the same type as the one supplied plus the `IDurableNonceTransaction` type. In particular, this method _prepends_ an instruction to the transaction designed to consume (or ‘advance’) the nonce in the same transaction whose lifetime is defined by it.
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
import { setTransactionLifetimeUsingDurableNonce } from '@solana/transactions';
|
|
125
|
+
|
|
126
|
+
const NONCE_VALUE_OFFSET =
|
|
127
|
+
4 + // version(u32)
|
|
128
|
+
4 + // state(u32)
|
|
129
|
+
32; // nonce authority(pubkey)
|
|
130
|
+
// Then comes the nonce value.
|
|
131
|
+
|
|
132
|
+
const nonceAccountAddress = address('EGtMh4yvXswwHhwVhyPxGrVV2TkLTgUqGodbATEPvojZ');
|
|
133
|
+
const nonceAuthorityAddress = address('4KD1Rdrd89NG7XbzW3xsX9Aqnx2EExJvExiNme6g9iAT');
|
|
134
|
+
const { value: nonceAccount } = await rpc
|
|
135
|
+
.getAccountInfo(nonceAccountAddress, {
|
|
136
|
+
dataSlice: { length: 32, offset: NONCE_VALUE_OFFSET },
|
|
137
|
+
encoding: 'base58',
|
|
138
|
+
})
|
|
139
|
+
.send();
|
|
140
|
+
const nonce =
|
|
141
|
+
// This works because we asked for the exact slice of data representing the nonce
|
|
142
|
+
// value, and furthermore asked for it in `base58` encoding.
|
|
143
|
+
nonceAccount!.data[0] as unknown as Nonce;
|
|
144
|
+
|
|
145
|
+
const durableNonceTransaction = setTransactionLifetimeUsingDurableNonce(
|
|
146
|
+
{ nonce, nonceAccountAddress, nonceAuthorityAddress },
|
|
147
|
+
tx,
|
|
148
|
+
);
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
#### `assertIsBlockhash()`
|
|
152
|
+
|
|
153
|
+
Client applications primarily deal with blockhashes in the form of base58-encoded strings. Blockhashes returned from the RPC API conform to the type `Blockhash`. You can use a value of that type wherever a blockhash is expected.
|
|
154
|
+
|
|
155
|
+
From time to time you might acquire a string, that you expect to validate as a blockhash, from an untrusted network API or user input. To assert that such an arbitrary string is a base58-encoded blockhash, use the `assertIsBlockhash` function.
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
import { assertIsBlockhash } from '@solana/transactions';
|
|
159
|
+
|
|
160
|
+
// Imagine a function that asserts whether a user-supplied blockhash is valid or not.
|
|
161
|
+
function handleSubmit() {
|
|
162
|
+
// We know only that what the user typed conforms to the `string` type.
|
|
163
|
+
const blockhash: string = blockhashInput.value;
|
|
164
|
+
try {
|
|
165
|
+
// If this type assertion function doesn't throw, then
|
|
166
|
+
// Typescript will upcast `blockhash` to `Blockhash`.
|
|
167
|
+
assertIsBlockhash(blockhash);
|
|
168
|
+
// At this point, `blockhash` is a `Blockhash` that can be used with the RPC.
|
|
169
|
+
const blockhashIsValid = await rpc.isBlockhashValid(blockhash).send();
|
|
170
|
+
} catch (e) {
|
|
171
|
+
// `blockhash` turned out not to be a base58-encoded blockhash
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
#### `assertIsDurableNonceTransaction()`
|
|
177
|
+
|
|
178
|
+
From time to time you might acquire a transaction that you expect to be a durable nonce transaction, from an untrusted network API or user input. To assert that such an arbitrary transaction is in fact a durable nonce transaction, use the `assertIsDurableNonceTransaction` function.
|
|
179
|
+
|
|
180
|
+
See [`assertIsBlockhash()`](#assertisblockhash) for an example of how to use an assertion function.
|
|
181
|
+
|
|
182
|
+
## Adding instructions to a transaction
|
|
183
|
+
|
|
184
|
+
### Types
|
|
185
|
+
|
|
186
|
+
#### `IInstruction`
|
|
187
|
+
|
|
188
|
+
This type represents an instruction to be issued to a program. Objects that conform to this type have a `programAddress` property that is the base58-encoded address of the program in question.
|
|
189
|
+
|
|
190
|
+
#### `IInstructionWithAccounts`
|
|
191
|
+
|
|
192
|
+
This type represents an instruction that specifies a list of accounts that a program may read from, write to, or require be signers of the transaction itself. Objects that conform to this type have an `accounts` property that is an array of `IAccountMeta | IAccountLookupMeta` in the order the instruction requires.
|
|
193
|
+
|
|
194
|
+
#### `IInstructionWithData`
|
|
195
|
+
|
|
196
|
+
This type represents an instruction that supplies some data as input to the program. Objects that conform to this type have a `data` property that can be any type of `Uint8Array`.
|
|
197
|
+
|
|
198
|
+
### Functions
|
|
199
|
+
|
|
200
|
+
#### `appendTransactionInstruction()`
|
|
201
|
+
|
|
202
|
+
Given an instruction, this method will return a new transaction with that instruction having been added to the end of the list of existing instructions.
|
|
203
|
+
|
|
204
|
+
```ts
|
|
205
|
+
import { address } from '@solana/addresses';
|
|
206
|
+
import { appendTransactionInstruction } from '@solana/transactions';
|
|
207
|
+
|
|
208
|
+
const memoTransaction = appendTransactionInstruction(
|
|
209
|
+
{
|
|
210
|
+
data: new TextEncoder().encode('Hello world!'),
|
|
211
|
+
programAddress: address('MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr'),
|
|
212
|
+
},
|
|
213
|
+
tx,
|
|
214
|
+
);
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
If you'd like to add multiple instructions to a transaction at once, you may use the `appendTransactionInstructions` function instead which accepts an array of instructions.
|
|
218
|
+
|
|
219
|
+
#### `prependTransactionInstruction()`
|
|
220
|
+
|
|
221
|
+
Given an instruction, this method will return a new transaction with that instruction having been added to the beginning of the list of existing instructions.
|
|
222
|
+
|
|
223
|
+
If you'd like to prepend multiple instructions to a transaction at once, you may use the `prependTransactionInstructions` function instead which accepts an array of instructions.
|
|
224
|
+
|
|
225
|
+
See [`appendTransactionInstruction()`](#appendtransactioninstruction) for an example of how to use this function.
|
|
226
|
+
|
|
227
|
+
## Signing transactions
|
|
228
|
+
|
|
229
|
+
In order to be landed on the network, a transaction must be signed by all of the private keys belonging to accounts that are required signers of the transaction.
|
|
230
|
+
|
|
231
|
+
Whether a transaction is ready to be signed or not is enforced for you at the type level. In order to be signable, a transaction must:
|
|
232
|
+
|
|
233
|
+
- have a version and a list of zero or more instructions (ie. conform to `BaseTransaction`)
|
|
234
|
+
- have a fee payer set (ie. conform to `ITransactionWithFeePayer`)
|
|
235
|
+
- have a lifetime specified (ie. conform to `ITransactionWithBlockhashLifetime | IDurableNonceTransaction`)
|
|
236
|
+
|
|
237
|
+
### Types
|
|
238
|
+
|
|
239
|
+
#### `ITransactionWithSignatures`
|
|
240
|
+
|
|
241
|
+
This type represents a transaction that is signed by at least one of its required signers. This type of transaction can be serialized to wire format, but is unsuitable for use with functions designed to land transaction on the network.
|
|
242
|
+
|
|
243
|
+
Expect any function that modifies a transaction (eg. `setTransactionFeePayer`, `appendTransactionInstruction`, et cetera) to delete a transaction's `signatures` property and unset this type.
|
|
244
|
+
|
|
245
|
+
#### `IFullySignedTransaction`
|
|
246
|
+
|
|
247
|
+
This type represents a transaction that is signed by all of its required signers. Being fully signed is a prerequisite of functions designed to land transactions on the network.
|
|
248
|
+
|
|
249
|
+
Expect any function that modifies a transaction (eg. `setTransactionFeePayer`, `appendTransactionInstruction`, et cetera) to delete a transaction's `signatures` property and unset this type.
|
|
250
|
+
|
|
251
|
+
### Functions
|
|
252
|
+
|
|
253
|
+
#### `getSignatureFromTransaction()`
|
|
254
|
+
|
|
255
|
+
Given a transaction signed by its fee payer, this method will return the `Signature` that uniquely identifies it. This string can be used to look up transactions at a later date, for example on a Solana block explorer.
|
|
256
|
+
|
|
257
|
+
```ts
|
|
258
|
+
import { getSignatureFromTransaction } from '@solana/transactions';
|
|
259
|
+
|
|
260
|
+
const signature = getSignatureFromTransaction(tx);
|
|
261
|
+
console.debug(`Inspect this transaction at https://explorer.solana.com/tx/${signature}`);
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
#### `signTransaction()`
|
|
265
|
+
|
|
266
|
+
Given an array of `CryptoKey` objects which are private keys pertaining to addresses that are required to sign a transaction, this method will return a new signed transaction having the same type as the one supplied plus the `ITransactionWithSignatures` type.
|
|
267
|
+
|
|
268
|
+
```ts
|
|
269
|
+
import { generateKeyPair } from '@solana/keys';
|
|
270
|
+
import { signTransaction } from '@solana/transactions';
|
|
271
|
+
|
|
272
|
+
const signedTransaction = await signTransaction([myPrivateKey], tx);
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Serializing transactions
|
|
276
|
+
|
|
277
|
+
Before sending a transaction to be landed on the network, you must serialize it in a particular way. You can use these types and functions to serialize a signed transaction into a binary format suitable for transit over the wire.
|
|
278
|
+
|
|
279
|
+
### Types
|
|
280
|
+
|
|
281
|
+
#### `Base64EncodedWireTransaction`
|
|
282
|
+
|
|
283
|
+
This type represents the wire format of a transaction as a base64-encoded string.
|
|
284
|
+
|
|
285
|
+
### Functions
|
|
286
|
+
|
|
287
|
+
#### `getBase64EncodedWireTransaction()`
|
|
288
|
+
|
|
289
|
+
Given a signed transaction, this method returns the transaction as a string that conforms to the `Base64EncodedWireTransaction` type.
|
|
290
|
+
|
|
291
|
+
```ts
|
|
292
|
+
import { getBase64EncodedWireTransaction, signTransaction } from '@solana/transactions';
|
|
293
|
+
|
|
294
|
+
const serializedTransaction = getBase64EncodedWireTransaction(signedTransaction);
|
|
295
|
+
const signature = await rpc.sendTransaction(serializedTransaction, { encoding: 'base64' }).send();
|
|
296
|
+
```
|