@solana/web3.js 0.0.0-next → 0.0.0-pr-29130
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/README.md +24 -25
- package/lib/index.browser.cjs.js +4583 -4238
- package/lib/index.browser.cjs.js.map +1 -1
- package/lib/index.browser.esm.js +4565 -4238
- package/lib/index.browser.esm.js.map +1 -1
- package/lib/index.cjs.js +7072 -3604
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +3516 -2420
- package/lib/index.esm.js +7046 -3601
- package/lib/index.esm.js.map +1 -1
- package/lib/index.iife.js +22171 -27053
- package/lib/index.iife.js.map +1 -1
- package/lib/index.iife.min.js +8 -33
- package/lib/index.iife.min.js.map +1 -1
- package/lib/index.native.js +10407 -0
- package/lib/index.native.js.map +1 -0
- package/package.json +36 -36
- package/src/__forks__/browser/fetch-impl.ts +4 -0
- package/src/__forks__/react-native/fetch-impl.ts +4 -0
- package/src/account-data.ts +39 -0
- package/src/account.ts +20 -11
- package/src/bpf-loader.ts +2 -2
- package/src/connection.ts +2303 -635
- package/src/epoch-schedule.ts +1 -1
- package/src/errors.ts +41 -0
- package/src/fee-calculator.ts +2 -0
- package/src/fetch-impl.ts +13 -0
- package/src/index.ts +3 -10
- package/src/keypair.ts +20 -25
- package/src/layout.ts +45 -4
- package/src/loader.ts +3 -3
- package/src/message/account-keys.ts +79 -0
- package/src/message/compiled-keys.ts +165 -0
- package/src/message/index.ts +47 -0
- package/src/{message.ts → message/legacy.ts} +95 -40
- package/src/message/v0.ts +496 -0
- package/src/message/versioned.ts +36 -0
- package/src/nonce-account.ts +8 -4
- package/src/programs/address-lookup-table/index.ts +435 -0
- package/src/programs/address-lookup-table/state.ts +84 -0
- package/src/programs/compute-budget.ts +281 -0
- package/src/{ed25519-program.ts → programs/ed25519.ts} +6 -6
- package/src/programs/index.ts +7 -0
- package/src/{secp256k1-program.ts → programs/secp256k1.ts} +15 -16
- package/src/{stake-program.ts → programs/stake.ts} +7 -7
- package/src/{system-program.ts → programs/system.ts} +55 -18
- package/src/{vote-program.ts → programs/vote.ts} +137 -9
- package/src/publickey.ts +37 -79
- package/src/transaction/constants.ts +12 -0
- package/src/transaction/expiry-custom-errors.ts +48 -0
- package/src/transaction/index.ts +5 -0
- package/src/{transaction.ts → transaction/legacy.ts} +162 -67
- package/src/transaction/message.ts +140 -0
- package/src/transaction/versioned.ts +126 -0
- package/src/{util → utils}/assert.ts +0 -0
- package/src/utils/bigint.ts +43 -0
- package/src/{util → utils}/borsh-schema.ts +0 -0
- package/src/{util → utils}/cluster.ts +0 -0
- package/src/utils/ed25519.ts +46 -0
- package/src/utils/index.ts +5 -0
- package/src/utils/makeWebsocketUrl.ts +26 -0
- package/src/{util → utils}/promise-timeout.ts +0 -0
- package/src/utils/secp256k1.ts +18 -0
- package/src/utils/send-and-confirm-raw-transaction.ts +105 -0
- package/src/utils/send-and-confirm-transaction.ts +98 -0
- package/src/{util → utils}/shortvec-encoding.ts +0 -0
- package/src/{util → utils}/sleep.ts +0 -0
- package/src/{util → utils}/to-buffer.ts +0 -0
- package/src/validator-info.ts +4 -6
- package/src/vote-account.ts +1 -1
- package/src/agent-manager.ts +0 -44
- package/src/util/send-and-confirm-raw-transaction.ts +0 -46
- package/src/util/send-and-confirm-transaction.ts +0 -50
- package/src/util/url.ts +0 -18
|
@@ -2,27 +2,20 @@ import bs58 from 'bs58';
|
|
|
2
2
|
import {Buffer} from 'buffer';
|
|
3
3
|
import * as BufferLayout from '@solana/buffer-layout';
|
|
4
4
|
|
|
5
|
-
import {PublicKey} from '
|
|
6
|
-
import type {Blockhash} from '
|
|
7
|
-
import * as Layout from '
|
|
8
|
-
import {PACKET_DATA_SIZE} from '
|
|
9
|
-
import * as shortvec from '
|
|
10
|
-
import {toBuffer} from '
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
*/
|
|
20
|
-
numRequiredSignatures: number;
|
|
21
|
-
/** The last `numReadonlySignedAccounts` of the signed keys are read-only accounts */
|
|
22
|
-
numReadonlySignedAccounts: number;
|
|
23
|
-
/** The last `numReadonlySignedAccounts` of the unsigned keys are read-only accounts */
|
|
24
|
-
numReadonlyUnsignedAccounts: number;
|
|
25
|
-
};
|
|
5
|
+
import {PublicKey, PUBLIC_KEY_LENGTH} from '../publickey';
|
|
6
|
+
import type {Blockhash} from '../blockhash';
|
|
7
|
+
import * as Layout from '../layout';
|
|
8
|
+
import {PACKET_DATA_SIZE, VERSION_PREFIX_MASK} from '../transaction/constants';
|
|
9
|
+
import * as shortvec from '../utils/shortvec-encoding';
|
|
10
|
+
import {toBuffer} from '../utils/to-buffer';
|
|
11
|
+
import {
|
|
12
|
+
MessageHeader,
|
|
13
|
+
MessageAddressTableLookup,
|
|
14
|
+
MessageCompiledInstruction,
|
|
15
|
+
} from './index';
|
|
16
|
+
import {TransactionInstruction} from '../transaction';
|
|
17
|
+
import {CompiledKeys} from './compiled-keys';
|
|
18
|
+
import {MessageAccountKeys} from './account-keys';
|
|
26
19
|
|
|
27
20
|
/**
|
|
28
21
|
* An instruction to execute by a program
|
|
@@ -47,14 +40,18 @@ export type MessageArgs = {
|
|
|
47
40
|
/** The message header, identifying signed and read-only `accountKeys` */
|
|
48
41
|
header: MessageHeader;
|
|
49
42
|
/** All the account keys used by this transaction */
|
|
50
|
-
accountKeys: string[];
|
|
43
|
+
accountKeys: string[] | PublicKey[];
|
|
51
44
|
/** The hash of a recent ledger block */
|
|
52
45
|
recentBlockhash: Blockhash;
|
|
53
46
|
/** Instructions that will be executed in sequence and committed in one atomic transaction if all succeed. */
|
|
54
47
|
instructions: CompiledInstruction[];
|
|
55
48
|
};
|
|
56
49
|
|
|
57
|
-
|
|
50
|
+
export type CompileLegacyArgs = {
|
|
51
|
+
payerKey: PublicKey;
|
|
52
|
+
instructions: Array<TransactionInstruction>;
|
|
53
|
+
recentBlockhash: Blockhash;
|
|
54
|
+
};
|
|
58
55
|
|
|
59
56
|
/**
|
|
60
57
|
* List of instructions to be processed atomically
|
|
@@ -83,19 +80,68 @@ export class Message {
|
|
|
83
80
|
);
|
|
84
81
|
}
|
|
85
82
|
|
|
83
|
+
get version(): 'legacy' {
|
|
84
|
+
return 'legacy';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
get staticAccountKeys(): Array<PublicKey> {
|
|
88
|
+
return this.accountKeys;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
get compiledInstructions(): Array<MessageCompiledInstruction> {
|
|
92
|
+
return this.instructions.map(
|
|
93
|
+
(ix): MessageCompiledInstruction => ({
|
|
94
|
+
programIdIndex: ix.programIdIndex,
|
|
95
|
+
accountKeyIndexes: ix.accounts,
|
|
96
|
+
data: bs58.decode(ix.data),
|
|
97
|
+
}),
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
get addressTableLookups(): Array<MessageAddressTableLookup> {
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
getAccountKeys(): MessageAccountKeys {
|
|
106
|
+
return new MessageAccountKeys(this.staticAccountKeys);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
static compile(args: CompileLegacyArgs): Message {
|
|
110
|
+
const compiledKeys = CompiledKeys.compile(args.instructions, args.payerKey);
|
|
111
|
+
const [header, staticAccountKeys] = compiledKeys.getMessageComponents();
|
|
112
|
+
const accountKeys = new MessageAccountKeys(staticAccountKeys);
|
|
113
|
+
const instructions = accountKeys.compileInstructions(args.instructions).map(
|
|
114
|
+
(ix: MessageCompiledInstruction): CompiledInstruction => ({
|
|
115
|
+
programIdIndex: ix.programIdIndex,
|
|
116
|
+
accounts: ix.accountKeyIndexes,
|
|
117
|
+
data: bs58.encode(ix.data),
|
|
118
|
+
}),
|
|
119
|
+
);
|
|
120
|
+
return new Message({
|
|
121
|
+
header,
|
|
122
|
+
accountKeys: staticAccountKeys,
|
|
123
|
+
recentBlockhash: args.recentBlockhash,
|
|
124
|
+
instructions,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
86
128
|
isAccountSigner(index: number): boolean {
|
|
87
129
|
return index < this.header.numRequiredSignatures;
|
|
88
130
|
}
|
|
89
131
|
|
|
90
132
|
isAccountWritable(index: number): boolean {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
133
|
+
const numSignedAccounts = this.header.numRequiredSignatures;
|
|
134
|
+
if (index >= this.header.numRequiredSignatures) {
|
|
135
|
+
const unsignedAccountIndex = index - numSignedAccounts;
|
|
136
|
+
const numUnsignedAccounts = this.accountKeys.length - numSignedAccounts;
|
|
137
|
+
const numWritableUnsignedAccounts =
|
|
138
|
+
numUnsignedAccounts - this.header.numReadonlyUnsignedAccounts;
|
|
139
|
+
return unsignedAccountIndex < numWritableUnsignedAccounts;
|
|
140
|
+
} else {
|
|
141
|
+
const numWritableSignedAccounts =
|
|
142
|
+
numSignedAccounts - this.header.numReadonlySignedAccounts;
|
|
143
|
+
return index < numWritableSignedAccounts;
|
|
144
|
+
}
|
|
99
145
|
}
|
|
100
146
|
|
|
101
147
|
isProgramId(index: number): boolean {
|
|
@@ -222,25 +268,34 @@ export class Message {
|
|
|
222
268
|
// Slice up wire data
|
|
223
269
|
let byteArray = [...buffer];
|
|
224
270
|
|
|
225
|
-
const numRequiredSignatures = byteArray.shift()
|
|
226
|
-
|
|
227
|
-
|
|
271
|
+
const numRequiredSignatures = byteArray.shift()!;
|
|
272
|
+
if (
|
|
273
|
+
numRequiredSignatures !==
|
|
274
|
+
(numRequiredSignatures & VERSION_PREFIX_MASK)
|
|
275
|
+
) {
|
|
276
|
+
throw new Error(
|
|
277
|
+
'Versioned messages must be deserialized with VersionedMessage.deserialize()',
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const numReadonlySignedAccounts = byteArray.shift()!;
|
|
282
|
+
const numReadonlyUnsignedAccounts = byteArray.shift()!;
|
|
228
283
|
|
|
229
284
|
const accountCount = shortvec.decodeLength(byteArray);
|
|
230
285
|
let accountKeys = [];
|
|
231
286
|
for (let i = 0; i < accountCount; i++) {
|
|
232
|
-
const account = byteArray.slice(0,
|
|
233
|
-
byteArray = byteArray.slice(
|
|
234
|
-
accountKeys.push(
|
|
287
|
+
const account = byteArray.slice(0, PUBLIC_KEY_LENGTH);
|
|
288
|
+
byteArray = byteArray.slice(PUBLIC_KEY_LENGTH);
|
|
289
|
+
accountKeys.push(new PublicKey(Buffer.from(account)));
|
|
235
290
|
}
|
|
236
291
|
|
|
237
|
-
const recentBlockhash = byteArray.slice(0,
|
|
238
|
-
byteArray = byteArray.slice(
|
|
292
|
+
const recentBlockhash = byteArray.slice(0, PUBLIC_KEY_LENGTH);
|
|
293
|
+
byteArray = byteArray.slice(PUBLIC_KEY_LENGTH);
|
|
239
294
|
|
|
240
295
|
const instructionCount = shortvec.decodeLength(byteArray);
|
|
241
296
|
let instructions: CompiledInstruction[] = [];
|
|
242
297
|
for (let i = 0; i < instructionCount; i++) {
|
|
243
|
-
const programIdIndex = byteArray.shift()
|
|
298
|
+
const programIdIndex = byteArray.shift()!;
|
|
244
299
|
const accountCount = shortvec.decodeLength(byteArray);
|
|
245
300
|
const accounts = byteArray.slice(0, accountCount);
|
|
246
301
|
byteArray = byteArray.slice(accountCount);
|
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
import bs58 from 'bs58';
|
|
2
|
+
import * as BufferLayout from '@solana/buffer-layout';
|
|
3
|
+
|
|
4
|
+
import * as Layout from '../layout';
|
|
5
|
+
import {Blockhash} from '../blockhash';
|
|
6
|
+
import {
|
|
7
|
+
MessageHeader,
|
|
8
|
+
MessageAddressTableLookup,
|
|
9
|
+
MessageCompiledInstruction,
|
|
10
|
+
} from './index';
|
|
11
|
+
import {PublicKey, PUBLIC_KEY_LENGTH} from '../publickey';
|
|
12
|
+
import * as shortvec from '../utils/shortvec-encoding';
|
|
13
|
+
import assert from '../utils/assert';
|
|
14
|
+
import {PACKET_DATA_SIZE, VERSION_PREFIX_MASK} from '../transaction/constants';
|
|
15
|
+
import {TransactionInstruction} from '../transaction';
|
|
16
|
+
import {AddressLookupTableAccount} from '../programs';
|
|
17
|
+
import {CompiledKeys} from './compiled-keys';
|
|
18
|
+
import {AccountKeysFromLookups, MessageAccountKeys} from './account-keys';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Message constructor arguments
|
|
22
|
+
*/
|
|
23
|
+
export type MessageV0Args = {
|
|
24
|
+
/** The message header, identifying signed and read-only `accountKeys` */
|
|
25
|
+
header: MessageHeader;
|
|
26
|
+
/** The static account keys used by this transaction */
|
|
27
|
+
staticAccountKeys: PublicKey[];
|
|
28
|
+
/** The hash of a recent ledger block */
|
|
29
|
+
recentBlockhash: Blockhash;
|
|
30
|
+
/** Instructions that will be executed in sequence and committed in one atomic transaction if all succeed. */
|
|
31
|
+
compiledInstructions: MessageCompiledInstruction[];
|
|
32
|
+
/** Instructions that will be executed in sequence and committed in one atomic transaction if all succeed. */
|
|
33
|
+
addressTableLookups: MessageAddressTableLookup[];
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export type CompileV0Args = {
|
|
37
|
+
payerKey: PublicKey;
|
|
38
|
+
instructions: Array<TransactionInstruction>;
|
|
39
|
+
recentBlockhash: Blockhash;
|
|
40
|
+
addressLookupTableAccounts?: Array<AddressLookupTableAccount>;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export type GetAccountKeysArgs =
|
|
44
|
+
| {
|
|
45
|
+
accountKeysFromLookups?: AccountKeysFromLookups | null;
|
|
46
|
+
}
|
|
47
|
+
| {
|
|
48
|
+
addressLookupTableAccounts?: AddressLookupTableAccount[] | null;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export class MessageV0 {
|
|
52
|
+
header: MessageHeader;
|
|
53
|
+
staticAccountKeys: Array<PublicKey>;
|
|
54
|
+
recentBlockhash: Blockhash;
|
|
55
|
+
compiledInstructions: Array<MessageCompiledInstruction>;
|
|
56
|
+
addressTableLookups: Array<MessageAddressTableLookup>;
|
|
57
|
+
|
|
58
|
+
constructor(args: MessageV0Args) {
|
|
59
|
+
this.header = args.header;
|
|
60
|
+
this.staticAccountKeys = args.staticAccountKeys;
|
|
61
|
+
this.recentBlockhash = args.recentBlockhash;
|
|
62
|
+
this.compiledInstructions = args.compiledInstructions;
|
|
63
|
+
this.addressTableLookups = args.addressTableLookups;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
get version(): 0 {
|
|
67
|
+
return 0;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
get numAccountKeysFromLookups(): number {
|
|
71
|
+
let count = 0;
|
|
72
|
+
for (const lookup of this.addressTableLookups) {
|
|
73
|
+
count += lookup.readonlyIndexes.length + lookup.writableIndexes.length;
|
|
74
|
+
}
|
|
75
|
+
return count;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
getAccountKeys(args?: GetAccountKeysArgs): MessageAccountKeys {
|
|
79
|
+
let accountKeysFromLookups: AccountKeysFromLookups | undefined;
|
|
80
|
+
if (
|
|
81
|
+
args &&
|
|
82
|
+
'accountKeysFromLookups' in args &&
|
|
83
|
+
args.accountKeysFromLookups
|
|
84
|
+
) {
|
|
85
|
+
if (
|
|
86
|
+
this.numAccountKeysFromLookups !=
|
|
87
|
+
args.accountKeysFromLookups.writable.length +
|
|
88
|
+
args.accountKeysFromLookups.readonly.length
|
|
89
|
+
) {
|
|
90
|
+
throw new Error(
|
|
91
|
+
'Failed to get account keys because of a mismatch in the number of account keys from lookups',
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
accountKeysFromLookups = args.accountKeysFromLookups;
|
|
95
|
+
} else if (
|
|
96
|
+
args &&
|
|
97
|
+
'addressLookupTableAccounts' in args &&
|
|
98
|
+
args.addressLookupTableAccounts
|
|
99
|
+
) {
|
|
100
|
+
accountKeysFromLookups = this.resolveAddressTableLookups(
|
|
101
|
+
args.addressLookupTableAccounts,
|
|
102
|
+
);
|
|
103
|
+
} else if (this.addressTableLookups.length > 0) {
|
|
104
|
+
throw new Error(
|
|
105
|
+
'Failed to get account keys because address table lookups were not resolved',
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
return new MessageAccountKeys(
|
|
109
|
+
this.staticAccountKeys,
|
|
110
|
+
accountKeysFromLookups,
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
isAccountSigner(index: number): boolean {
|
|
115
|
+
return index < this.header.numRequiredSignatures;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
isAccountWritable(index: number): boolean {
|
|
119
|
+
const numSignedAccounts = this.header.numRequiredSignatures;
|
|
120
|
+
const numStaticAccountKeys = this.staticAccountKeys.length;
|
|
121
|
+
if (index >= numStaticAccountKeys) {
|
|
122
|
+
const lookupAccountKeysIndex = index - numStaticAccountKeys;
|
|
123
|
+
const numWritableLookupAccountKeys = this.addressTableLookups.reduce(
|
|
124
|
+
(count, lookup) => count + lookup.writableIndexes.length,
|
|
125
|
+
0,
|
|
126
|
+
);
|
|
127
|
+
return lookupAccountKeysIndex < numWritableLookupAccountKeys;
|
|
128
|
+
} else if (index >= this.header.numRequiredSignatures) {
|
|
129
|
+
const unsignedAccountIndex = index - numSignedAccounts;
|
|
130
|
+
const numUnsignedAccounts = numStaticAccountKeys - numSignedAccounts;
|
|
131
|
+
const numWritableUnsignedAccounts =
|
|
132
|
+
numUnsignedAccounts - this.header.numReadonlyUnsignedAccounts;
|
|
133
|
+
return unsignedAccountIndex < numWritableUnsignedAccounts;
|
|
134
|
+
} else {
|
|
135
|
+
const numWritableSignedAccounts =
|
|
136
|
+
numSignedAccounts - this.header.numReadonlySignedAccounts;
|
|
137
|
+
return index < numWritableSignedAccounts;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
resolveAddressTableLookups(
|
|
142
|
+
addressLookupTableAccounts: AddressLookupTableAccount[],
|
|
143
|
+
): AccountKeysFromLookups {
|
|
144
|
+
const accountKeysFromLookups: AccountKeysFromLookups = {
|
|
145
|
+
writable: [],
|
|
146
|
+
readonly: [],
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
for (const tableLookup of this.addressTableLookups) {
|
|
150
|
+
const tableAccount = addressLookupTableAccounts.find(account =>
|
|
151
|
+
account.key.equals(tableLookup.accountKey),
|
|
152
|
+
);
|
|
153
|
+
if (!tableAccount) {
|
|
154
|
+
throw new Error(
|
|
155
|
+
`Failed to find address lookup table account for table key ${tableLookup.accountKey.toBase58()}`,
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
for (const index of tableLookup.writableIndexes) {
|
|
160
|
+
if (index < tableAccount.state.addresses.length) {
|
|
161
|
+
accountKeysFromLookups.writable.push(
|
|
162
|
+
tableAccount.state.addresses[index],
|
|
163
|
+
);
|
|
164
|
+
} else {
|
|
165
|
+
throw new Error(
|
|
166
|
+
`Failed to find address for index ${index} in address lookup table ${tableLookup.accountKey.toBase58()}`,
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
for (const index of tableLookup.readonlyIndexes) {
|
|
172
|
+
if (index < tableAccount.state.addresses.length) {
|
|
173
|
+
accountKeysFromLookups.readonly.push(
|
|
174
|
+
tableAccount.state.addresses[index],
|
|
175
|
+
);
|
|
176
|
+
} else {
|
|
177
|
+
throw new Error(
|
|
178
|
+
`Failed to find address for index ${index} in address lookup table ${tableLookup.accountKey.toBase58()}`,
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return accountKeysFromLookups;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
static compile(args: CompileV0Args): MessageV0 {
|
|
188
|
+
const compiledKeys = CompiledKeys.compile(args.instructions, args.payerKey);
|
|
189
|
+
|
|
190
|
+
const addressTableLookups = new Array<MessageAddressTableLookup>();
|
|
191
|
+
const accountKeysFromLookups: AccountKeysFromLookups = {
|
|
192
|
+
writable: new Array(),
|
|
193
|
+
readonly: new Array(),
|
|
194
|
+
};
|
|
195
|
+
const lookupTableAccounts = args.addressLookupTableAccounts || [];
|
|
196
|
+
for (const lookupTable of lookupTableAccounts) {
|
|
197
|
+
const extractResult = compiledKeys.extractTableLookup(lookupTable);
|
|
198
|
+
if (extractResult !== undefined) {
|
|
199
|
+
const [addressTableLookup, {writable, readonly}] = extractResult;
|
|
200
|
+
addressTableLookups.push(addressTableLookup);
|
|
201
|
+
accountKeysFromLookups.writable.push(...writable);
|
|
202
|
+
accountKeysFromLookups.readonly.push(...readonly);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const [header, staticAccountKeys] = compiledKeys.getMessageComponents();
|
|
207
|
+
const accountKeys = new MessageAccountKeys(
|
|
208
|
+
staticAccountKeys,
|
|
209
|
+
accountKeysFromLookups,
|
|
210
|
+
);
|
|
211
|
+
const compiledInstructions = accountKeys.compileInstructions(
|
|
212
|
+
args.instructions,
|
|
213
|
+
);
|
|
214
|
+
return new MessageV0({
|
|
215
|
+
header,
|
|
216
|
+
staticAccountKeys,
|
|
217
|
+
recentBlockhash: args.recentBlockhash,
|
|
218
|
+
compiledInstructions,
|
|
219
|
+
addressTableLookups,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
serialize(): Uint8Array {
|
|
224
|
+
const encodedStaticAccountKeysLength = Array<number>();
|
|
225
|
+
shortvec.encodeLength(
|
|
226
|
+
encodedStaticAccountKeysLength,
|
|
227
|
+
this.staticAccountKeys.length,
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
const serializedInstructions = this.serializeInstructions();
|
|
231
|
+
const encodedInstructionsLength = Array<number>();
|
|
232
|
+
shortvec.encodeLength(
|
|
233
|
+
encodedInstructionsLength,
|
|
234
|
+
this.compiledInstructions.length,
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
const serializedAddressTableLookups = this.serializeAddressTableLookups();
|
|
238
|
+
const encodedAddressTableLookupsLength = Array<number>();
|
|
239
|
+
shortvec.encodeLength(
|
|
240
|
+
encodedAddressTableLookupsLength,
|
|
241
|
+
this.addressTableLookups.length,
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
const messageLayout = BufferLayout.struct<{
|
|
245
|
+
prefix: number;
|
|
246
|
+
header: MessageHeader;
|
|
247
|
+
staticAccountKeysLength: Uint8Array;
|
|
248
|
+
staticAccountKeys: Array<Uint8Array>;
|
|
249
|
+
recentBlockhash: Uint8Array;
|
|
250
|
+
instructionsLength: Uint8Array;
|
|
251
|
+
serializedInstructions: Uint8Array;
|
|
252
|
+
addressTableLookupsLength: Uint8Array;
|
|
253
|
+
serializedAddressTableLookups: Uint8Array;
|
|
254
|
+
}>([
|
|
255
|
+
BufferLayout.u8('prefix'),
|
|
256
|
+
BufferLayout.struct<MessageHeader>(
|
|
257
|
+
[
|
|
258
|
+
BufferLayout.u8('numRequiredSignatures'),
|
|
259
|
+
BufferLayout.u8('numReadonlySignedAccounts'),
|
|
260
|
+
BufferLayout.u8('numReadonlyUnsignedAccounts'),
|
|
261
|
+
],
|
|
262
|
+
'header',
|
|
263
|
+
),
|
|
264
|
+
BufferLayout.blob(
|
|
265
|
+
encodedStaticAccountKeysLength.length,
|
|
266
|
+
'staticAccountKeysLength',
|
|
267
|
+
),
|
|
268
|
+
BufferLayout.seq(
|
|
269
|
+
Layout.publicKey(),
|
|
270
|
+
this.staticAccountKeys.length,
|
|
271
|
+
'staticAccountKeys',
|
|
272
|
+
),
|
|
273
|
+
Layout.publicKey('recentBlockhash'),
|
|
274
|
+
BufferLayout.blob(encodedInstructionsLength.length, 'instructionsLength'),
|
|
275
|
+
BufferLayout.blob(
|
|
276
|
+
serializedInstructions.length,
|
|
277
|
+
'serializedInstructions',
|
|
278
|
+
),
|
|
279
|
+
BufferLayout.blob(
|
|
280
|
+
encodedAddressTableLookupsLength.length,
|
|
281
|
+
'addressTableLookupsLength',
|
|
282
|
+
),
|
|
283
|
+
BufferLayout.blob(
|
|
284
|
+
serializedAddressTableLookups.length,
|
|
285
|
+
'serializedAddressTableLookups',
|
|
286
|
+
),
|
|
287
|
+
]);
|
|
288
|
+
|
|
289
|
+
const serializedMessage = new Uint8Array(PACKET_DATA_SIZE);
|
|
290
|
+
const MESSAGE_VERSION_0_PREFIX = 1 << 7;
|
|
291
|
+
const serializedMessageLength = messageLayout.encode(
|
|
292
|
+
{
|
|
293
|
+
prefix: MESSAGE_VERSION_0_PREFIX,
|
|
294
|
+
header: this.header,
|
|
295
|
+
staticAccountKeysLength: new Uint8Array(encodedStaticAccountKeysLength),
|
|
296
|
+
staticAccountKeys: this.staticAccountKeys.map(key => key.toBytes()),
|
|
297
|
+
recentBlockhash: bs58.decode(this.recentBlockhash),
|
|
298
|
+
instructionsLength: new Uint8Array(encodedInstructionsLength),
|
|
299
|
+
serializedInstructions,
|
|
300
|
+
addressTableLookupsLength: new Uint8Array(
|
|
301
|
+
encodedAddressTableLookupsLength,
|
|
302
|
+
),
|
|
303
|
+
serializedAddressTableLookups,
|
|
304
|
+
},
|
|
305
|
+
serializedMessage,
|
|
306
|
+
);
|
|
307
|
+
return serializedMessage.slice(0, serializedMessageLength);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
private serializeInstructions(): Uint8Array {
|
|
311
|
+
let serializedLength = 0;
|
|
312
|
+
const serializedInstructions = new Uint8Array(PACKET_DATA_SIZE);
|
|
313
|
+
for (const instruction of this.compiledInstructions) {
|
|
314
|
+
const encodedAccountKeyIndexesLength = Array<number>();
|
|
315
|
+
shortvec.encodeLength(
|
|
316
|
+
encodedAccountKeyIndexesLength,
|
|
317
|
+
instruction.accountKeyIndexes.length,
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
const encodedDataLength = Array<number>();
|
|
321
|
+
shortvec.encodeLength(encodedDataLength, instruction.data.length);
|
|
322
|
+
|
|
323
|
+
const instructionLayout = BufferLayout.struct<{
|
|
324
|
+
programIdIndex: number;
|
|
325
|
+
encodedAccountKeyIndexesLength: Uint8Array;
|
|
326
|
+
accountKeyIndexes: number[];
|
|
327
|
+
encodedDataLength: Uint8Array;
|
|
328
|
+
data: Uint8Array;
|
|
329
|
+
}>([
|
|
330
|
+
BufferLayout.u8('programIdIndex'),
|
|
331
|
+
BufferLayout.blob(
|
|
332
|
+
encodedAccountKeyIndexesLength.length,
|
|
333
|
+
'encodedAccountKeyIndexesLength',
|
|
334
|
+
),
|
|
335
|
+
BufferLayout.seq(
|
|
336
|
+
BufferLayout.u8(),
|
|
337
|
+
instruction.accountKeyIndexes.length,
|
|
338
|
+
'accountKeyIndexes',
|
|
339
|
+
),
|
|
340
|
+
BufferLayout.blob(encodedDataLength.length, 'encodedDataLength'),
|
|
341
|
+
BufferLayout.blob(instruction.data.length, 'data'),
|
|
342
|
+
]);
|
|
343
|
+
|
|
344
|
+
serializedLength += instructionLayout.encode(
|
|
345
|
+
{
|
|
346
|
+
programIdIndex: instruction.programIdIndex,
|
|
347
|
+
encodedAccountKeyIndexesLength: new Uint8Array(
|
|
348
|
+
encodedAccountKeyIndexesLength,
|
|
349
|
+
),
|
|
350
|
+
accountKeyIndexes: instruction.accountKeyIndexes,
|
|
351
|
+
encodedDataLength: new Uint8Array(encodedDataLength),
|
|
352
|
+
data: instruction.data,
|
|
353
|
+
},
|
|
354
|
+
serializedInstructions,
|
|
355
|
+
serializedLength,
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return serializedInstructions.slice(0, serializedLength);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
private serializeAddressTableLookups(): Uint8Array {
|
|
363
|
+
let serializedLength = 0;
|
|
364
|
+
const serializedAddressTableLookups = new Uint8Array(PACKET_DATA_SIZE);
|
|
365
|
+
for (const lookup of this.addressTableLookups) {
|
|
366
|
+
const encodedWritableIndexesLength = Array<number>();
|
|
367
|
+
shortvec.encodeLength(
|
|
368
|
+
encodedWritableIndexesLength,
|
|
369
|
+
lookup.writableIndexes.length,
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
const encodedReadonlyIndexesLength = Array<number>();
|
|
373
|
+
shortvec.encodeLength(
|
|
374
|
+
encodedReadonlyIndexesLength,
|
|
375
|
+
lookup.readonlyIndexes.length,
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
const addressTableLookupLayout = BufferLayout.struct<{
|
|
379
|
+
accountKey: Uint8Array;
|
|
380
|
+
encodedWritableIndexesLength: Uint8Array;
|
|
381
|
+
writableIndexes: number[];
|
|
382
|
+
encodedReadonlyIndexesLength: Uint8Array;
|
|
383
|
+
readonlyIndexes: number[];
|
|
384
|
+
}>([
|
|
385
|
+
Layout.publicKey('accountKey'),
|
|
386
|
+
BufferLayout.blob(
|
|
387
|
+
encodedWritableIndexesLength.length,
|
|
388
|
+
'encodedWritableIndexesLength',
|
|
389
|
+
),
|
|
390
|
+
BufferLayout.seq(
|
|
391
|
+
BufferLayout.u8(),
|
|
392
|
+
lookup.writableIndexes.length,
|
|
393
|
+
'writableIndexes',
|
|
394
|
+
),
|
|
395
|
+
BufferLayout.blob(
|
|
396
|
+
encodedReadonlyIndexesLength.length,
|
|
397
|
+
'encodedReadonlyIndexesLength',
|
|
398
|
+
),
|
|
399
|
+
BufferLayout.seq(
|
|
400
|
+
BufferLayout.u8(),
|
|
401
|
+
lookup.readonlyIndexes.length,
|
|
402
|
+
'readonlyIndexes',
|
|
403
|
+
),
|
|
404
|
+
]);
|
|
405
|
+
|
|
406
|
+
serializedLength += addressTableLookupLayout.encode(
|
|
407
|
+
{
|
|
408
|
+
accountKey: lookup.accountKey.toBytes(),
|
|
409
|
+
encodedWritableIndexesLength: new Uint8Array(
|
|
410
|
+
encodedWritableIndexesLength,
|
|
411
|
+
),
|
|
412
|
+
writableIndexes: lookup.writableIndexes,
|
|
413
|
+
encodedReadonlyIndexesLength: new Uint8Array(
|
|
414
|
+
encodedReadonlyIndexesLength,
|
|
415
|
+
),
|
|
416
|
+
readonlyIndexes: lookup.readonlyIndexes,
|
|
417
|
+
},
|
|
418
|
+
serializedAddressTableLookups,
|
|
419
|
+
serializedLength,
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
return serializedAddressTableLookups.slice(0, serializedLength);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
static deserialize(serializedMessage: Uint8Array): MessageV0 {
|
|
427
|
+
let byteArray = [...serializedMessage];
|
|
428
|
+
|
|
429
|
+
const prefix = byteArray.shift() as number;
|
|
430
|
+
const maskedPrefix = prefix & VERSION_PREFIX_MASK;
|
|
431
|
+
assert(
|
|
432
|
+
prefix !== maskedPrefix,
|
|
433
|
+
`Expected versioned message but received legacy message`,
|
|
434
|
+
);
|
|
435
|
+
|
|
436
|
+
const version = maskedPrefix;
|
|
437
|
+
assert(
|
|
438
|
+
version === 0,
|
|
439
|
+
`Expected versioned message with version 0 but found version ${version}`,
|
|
440
|
+
);
|
|
441
|
+
|
|
442
|
+
const header: MessageHeader = {
|
|
443
|
+
numRequiredSignatures: byteArray.shift() as number,
|
|
444
|
+
numReadonlySignedAccounts: byteArray.shift() as number,
|
|
445
|
+
numReadonlyUnsignedAccounts: byteArray.shift() as number,
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
const staticAccountKeys = [];
|
|
449
|
+
const staticAccountKeysLength = shortvec.decodeLength(byteArray);
|
|
450
|
+
for (let i = 0; i < staticAccountKeysLength; i++) {
|
|
451
|
+
staticAccountKeys.push(
|
|
452
|
+
new PublicKey(byteArray.splice(0, PUBLIC_KEY_LENGTH)),
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
const recentBlockhash = bs58.encode(byteArray.splice(0, PUBLIC_KEY_LENGTH));
|
|
457
|
+
|
|
458
|
+
const instructionCount = shortvec.decodeLength(byteArray);
|
|
459
|
+
const compiledInstructions: MessageCompiledInstruction[] = [];
|
|
460
|
+
for (let i = 0; i < instructionCount; i++) {
|
|
461
|
+
const programIdIndex = byteArray.shift() as number;
|
|
462
|
+
const accountKeyIndexesLength = shortvec.decodeLength(byteArray);
|
|
463
|
+
const accountKeyIndexes = byteArray.splice(0, accountKeyIndexesLength);
|
|
464
|
+
const dataLength = shortvec.decodeLength(byteArray);
|
|
465
|
+
const data = new Uint8Array(byteArray.splice(0, dataLength));
|
|
466
|
+
compiledInstructions.push({
|
|
467
|
+
programIdIndex,
|
|
468
|
+
accountKeyIndexes,
|
|
469
|
+
data,
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
const addressTableLookupsCount = shortvec.decodeLength(byteArray);
|
|
474
|
+
const addressTableLookups: MessageAddressTableLookup[] = [];
|
|
475
|
+
for (let i = 0; i < addressTableLookupsCount; i++) {
|
|
476
|
+
const accountKey = new PublicKey(byteArray.splice(0, PUBLIC_KEY_LENGTH));
|
|
477
|
+
const writableIndexesLength = shortvec.decodeLength(byteArray);
|
|
478
|
+
const writableIndexes = byteArray.splice(0, writableIndexesLength);
|
|
479
|
+
const readonlyIndexesLength = shortvec.decodeLength(byteArray);
|
|
480
|
+
const readonlyIndexes = byteArray.splice(0, readonlyIndexesLength);
|
|
481
|
+
addressTableLookups.push({
|
|
482
|
+
accountKey,
|
|
483
|
+
writableIndexes,
|
|
484
|
+
readonlyIndexes,
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
return new MessageV0({
|
|
489
|
+
header,
|
|
490
|
+
staticAccountKeys,
|
|
491
|
+
recentBlockhash,
|
|
492
|
+
compiledInstructions,
|
|
493
|
+
addressTableLookups,
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
}
|