@solana/compat 2.0.0-experimental.72efece → 2.0.0-experimental.745437f

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 CHANGED
@@ -16,10 +16,46 @@
16
16
 
17
17
  This package contains utilities for converting from legacy web3js classes to the new data structures. 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
- ## Types
19
+ ## Functions
20
20
 
21
- TODO
21
+ ### `fromLegacyPublicKey()`
22
22
 
23
- ## Functions
23
+ This can be used to convert a legacy `PublicKey` object to an `Address` type
24
+
25
+ ```ts
26
+ import { fromLegacyPublicKey } from '@solana/compat';
27
+ const address = fromLegacyPublicKey(new PublicKey('49XBVQsvSW44ULKL9qufS9YqQPbdcps1TQRijx4FQ9sH'));
28
+ ```
29
+
30
+ ### `fromLegacyKeypair()`
31
+
32
+ This can be used to convert a legacy `Keypair` object to a native Ed25519 `CryptoKeyPair` object
33
+
34
+ ```ts
35
+ import { fromLegaycKeypair } from '@solana/compat';
36
+ const { privateKey, publicKey } = await fromLegacyKeypair(Keypair.generate());
37
+ ```
38
+
39
+ ### `fromVersionedTransactionWithBlockhash()`
40
+
41
+ This can be used to convert a legacy `VersionedTransaction` object that uses a blockhash lifetime to a `Transaction` object. The returned transaction fulfils both the `ITransactionWithFeePayer` and `ITransactionWithBlockhash` interfaces.
42
+
43
+ ```ts
44
+ import { fromVersionedTransactionWithBlockhash } from '@solana/compat';
45
+
46
+ // imagine a function that returns a legacy `VersionedTransaction`
47
+ const legacyVersionedTransaction = getMyLegacyVersionedTransaction();
48
+ const transaction = fromVersionedTransactionWithBlockhash(legacyVersionedTransaction);
49
+ ```
50
+
51
+ ### `fromVersionedTransactionWithDurableNonce()`
52
+
53
+ This can be used to convert a legacy `VersionedTransaction` object that uses a durable nonce lifetime to a `Transaction` object. The returned transaction fulfils both the `ITransactionWithFeePayer` and `IDurableNonceTransaction` interfaces.
54
+
55
+ ```ts
56
+ import { fromVersionedTransactionWithDurableNonce } from '@solana/compat';
24
57
 
25
- TODO
58
+ // imagine a function that returns a legacy `VersionedTransaction`
59
+ const legacyVersionedTransaction = getMyLegacyVersionedTransaction();
60
+ const transaction = fromVersionedTransactionWithDurableNonce(legacyVersionedTransaction);
61
+ ```
@@ -1,10 +1,115 @@
1
1
  'use strict';
2
2
 
3
+ var keys = require('@solana/keys');
3
4
  var functional = require('@solana/functional');
4
5
  var instructions = require('@solana/instructions');
5
6
  var transactions = require('@solana/transactions');
6
7
 
7
- // src/transaction.ts
8
+ // src/address.ts
9
+ function fromLegacyPublicKey(publicKey) {
10
+ return publicKey.toBase58();
11
+ }
12
+ async function fromLegacyKeypair(keypair, extractable) {
13
+ const [publicKey, privateKey] = await Promise.all([
14
+ crypto.subtle.importKey("raw", keypair.publicKey.toBytes(), "Ed25519", true, ["verify"]),
15
+ keys.createPrivateKeyFromBytes(keypair.secretKey.slice(0, 32), extractable)
16
+ ]);
17
+ return {
18
+ privateKey,
19
+ publicKey
20
+ };
21
+ }
22
+
23
+ // ../codecs-core/dist/index.browser.js
24
+ function getEncodedSize(value, encoder) {
25
+ return "fixedSize" in encoder ? encoder.fixedSize : encoder.getSizeFromValue(value);
26
+ }
27
+ function createEncoder(encoder) {
28
+ return Object.freeze({
29
+ ...encoder,
30
+ encode: (value) => {
31
+ const bytes = new Uint8Array(getEncodedSize(value, encoder));
32
+ encoder.write(value, bytes, 0);
33
+ return bytes;
34
+ }
35
+ });
36
+ }
37
+
38
+ // ../codecs-strings/dist/index.browser.js
39
+ function assertValidBaseString(alphabet4, testValue, givenValue = testValue) {
40
+ if (!testValue.match(new RegExp(`^[${alphabet4}]*$`))) {
41
+ throw new Error(`Expected a string of base ${alphabet4.length}, got [${givenValue}].`);
42
+ }
43
+ }
44
+ var getBaseXEncoder = (alphabet4) => {
45
+ return createEncoder({
46
+ getSizeFromValue: (value) => {
47
+ const [leadingZeroes, tailChars] = partitionLeadingZeroes(value, alphabet4[0]);
48
+ if (tailChars === "")
49
+ return value.length;
50
+ const base10Number = getBigIntFromBaseX(tailChars, alphabet4);
51
+ return leadingZeroes.length + Math.ceil(base10Number.toString(16).length / 2);
52
+ },
53
+ write(value, bytes, offset) {
54
+ assertValidBaseString(alphabet4, value);
55
+ if (value === "")
56
+ return offset;
57
+ const [leadingZeroes, tailChars] = partitionLeadingZeroes(value, alphabet4[0]);
58
+ if (tailChars === "") {
59
+ bytes.set(new Uint8Array(leadingZeroes.length).fill(0), offset);
60
+ return offset + leadingZeroes.length;
61
+ }
62
+ let base10Number = getBigIntFromBaseX(tailChars, alphabet4);
63
+ const tailBytes = [];
64
+ while (base10Number > 0n) {
65
+ tailBytes.unshift(Number(base10Number % 256n));
66
+ base10Number /= 256n;
67
+ }
68
+ const bytesToAdd = [...Array(leadingZeroes.length).fill(0), ...tailBytes];
69
+ bytes.set(bytesToAdd, offset);
70
+ return offset + bytesToAdd.length;
71
+ }
72
+ });
73
+ };
74
+ function partitionLeadingZeroes(value, zeroCharacter) {
75
+ const leadingZeroIndex = [...value].findIndex((c) => c !== zeroCharacter);
76
+ return leadingZeroIndex === -1 ? [value, ""] : [value.slice(0, leadingZeroIndex), value.slice(leadingZeroIndex)];
77
+ }
78
+ function getBigIntFromBaseX(value, alphabet4) {
79
+ const base = BigInt(alphabet4.length);
80
+ return [...value].reduce((sum, char) => sum * base + BigInt(alphabet4.indexOf(char)), 0n);
81
+ }
82
+ var alphabet2 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
83
+ var getBase58Encoder = () => getBaseXEncoder(alphabet2);
84
+
85
+ // ../addresses/dist/index.browser.js
86
+ var memoizedBase58Encoder;
87
+ function getMemoizedBase58Encoder() {
88
+ if (!memoizedBase58Encoder)
89
+ memoizedBase58Encoder = getBase58Encoder();
90
+ return memoizedBase58Encoder;
91
+ }
92
+ function assertIsAddress(putativeAddress) {
93
+ try {
94
+ if (
95
+ // Lowest address (32 bytes of zeroes)
96
+ putativeAddress.length < 32 || // Highest address (32 bytes of 255)
97
+ putativeAddress.length > 44
98
+ ) {
99
+ throw new Error("Expected input string to decode to a byte array of length 32.");
100
+ }
101
+ const base58Encoder = getMemoizedBase58Encoder();
102
+ const bytes = base58Encoder.encode(putativeAddress);
103
+ const numBytes = bytes.byteLength;
104
+ if (numBytes !== 32) {
105
+ throw new Error(`Expected input string to decode to a byte array of length 32. Actual length: ${numBytes}`);
106
+ }
107
+ } catch (e2) {
108
+ throw new Error(`\`${putativeAddress}\` is not a base-58 encoded address`, {
109
+ cause: e2
110
+ });
111
+ }
112
+ }
8
113
  function convertAccount(message, accountKeys, accountIndex) {
9
114
  const accountPublicKey = accountKeys.get(accountIndex);
10
115
  if (!accountPublicKey) {
@@ -68,7 +173,47 @@ function fromVersionedTransactionWithBlockhash(transaction, lastValidBlockHeight
68
173
  (tx) => transaction.signatures.length ? { ...tx, signatures } : tx
69
174
  );
70
175
  }
176
+ function fromVersionedTransactionWithDurableNonce(transaction) {
177
+ if (transaction.message.addressTableLookups.length > 0) {
178
+ throw new Error("Cannot convert transaction with addressTableLookups");
179
+ }
180
+ const accountKeys = transaction.message.getAccountKeys();
181
+ const feePayer = accountKeys.staticAccountKeys[0];
182
+ if (!feePayer)
183
+ throw new Error("No fee payer set in VersionedTransaction");
184
+ const instructions = transaction.message.compiledInstructions.map(
185
+ (instruction) => convertInstruction(transaction.message, accountKeys, instruction)
186
+ );
187
+ if (instructions.length === 0) {
188
+ throw new Error("transaction with no instructions cannot be durable nonce transaction");
189
+ }
190
+ if (!transactions.isAdvanceNonceAccountInstruction(instructions[0])) {
191
+ throw new Error("transaction first instruction is not advance nonce account instruction");
192
+ }
193
+ const nonceAccountAddress = instructions[0].accounts[0].address;
194
+ assertIsAddress(nonceAccountAddress);
195
+ const nonceAuthorityAddress = instructions[0].accounts[2].address;
196
+ assertIsAddress(nonceAuthorityAddress);
197
+ const durableNonceLifetime = {
198
+ nonce: transaction.message.recentBlockhash,
199
+ nonceAccountAddress,
200
+ nonceAuthorityAddress
201
+ };
202
+ const signatures = convertSignatures(transaction, accountKeys.staticAccountKeys);
203
+ return functional.pipe(
204
+ transactions.createTransaction({ version: transaction.version }),
205
+ (tx) => transactions.setTransactionFeePayer(feePayer.toBase58(), tx),
206
+ (tx) => transactions.setTransactionLifetimeUsingDurableNonce(durableNonceLifetime, tx),
207
+ (tx) => instructions.slice(1).reduce((acc, instruction) => {
208
+ return transactions.appendTransactionInstruction(instruction, acc);
209
+ }, tx),
210
+ (tx) => transaction.signatures.length ? { ...tx, signatures } : tx
211
+ );
212
+ }
71
213
 
214
+ exports.fromLegacyKeypair = fromLegacyKeypair;
215
+ exports.fromLegacyPublicKey = fromLegacyPublicKey;
72
216
  exports.fromVersionedTransactionWithBlockhash = fromVersionedTransactionWithBlockhash;
217
+ exports.fromVersionedTransactionWithDurableNonce = fromVersionedTransactionWithDurableNonce;
73
218
  //# sourceMappingURL=out.js.map
74
219
  //# sourceMappingURL=index.browser.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/transaction.ts"],"names":[],"mappings":";AACA,SAAS,YAAY;AAErB,SAAS,mBAAmB;AAS5B;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACG;AASP,SAAS,eACL,SACA,aACA,cACY;AACZ,QAAM,mBAAmB,YAAY,IAAI,YAAY;AACrD,MAAI,CAAC,kBAAkB;AAEnB,UAAM,IAAI,MAAM,2CAA2C,YAAY,EAAE;AAAA,EAC7E;AACA,QAAM,WAAW,QAAQ,gBAAgB,YAAY;AACrD,QAAM,aAAa,QAAQ,kBAAkB,YAAY;AAEzD,QAAM,OAAO,WACP,aACI,YAAY,kBACZ,YAAY,kBAChB,aACA,YAAY,WACZ,YAAY;AAElB,SAAO;AAAA,IACH,SAAS,iBAAiB,SAAS;AAAA,IACnC;AAAA,EACJ;AACJ;AAEA,SAAS,mBACL,SACA,aACA,aACY;AACZ,QAAM,0BAA0B,YAAY,IAAI,YAAY,cAAc;AAC1E,MAAI,CAAC,yBAAyB;AAE1B,UAAM,IAAI,MAAM,2CAA2C,YAAY,cAAc,EAAE;AAAA,EAC3F;AAEA,QAAM,WAAW,YAAY,kBAAkB;AAAA,IAAI,kBAC/C,eAAe,SAAS,aAAa,YAAY;AAAA,EACrD;AAEA,SAAO;AAAA,IACH,gBAAgB,wBAAwB,SAAS;AAAA,IACjD,GAAI,SAAS,SAAS,EAAE,SAAS,IAAI,CAAC;AAAA,IACtC,GAAI,YAAY,KAAK,SAAS,EAAE,MAAM,YAAY,KAAK,IAAI,CAAC;AAAA,EAChE;AACJ;AAEA,SAAS,kBACL,aACA,mBACwC;AACxC,SAAO,YAAY,WAAW,OAAO,CAAC,KAAK,KAAK,UAAU;AAGtD,UAAM,WAAW,IAAI,MAAM,UAAQ,SAAS,CAAC;AAC7C,QAAI;AAAU,aAAO;AAErB,UAAM,UAAU,kBAAkB,KAAK,EAAE,SAAS;AAClD,WAAO,EAAE,GAAG,KAAK,CAAC,OAAO,GAAG,IAAwB;AAAA,EACxD,GAAG,CAAC,CAAC;AACT;AAEO,SAAS,sCACZ,aACA,sBAC0E;AAI1E,MAAI,YAAY,QAAQ,oBAAoB,SAAS,GAAG;AAEpD,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACzE;AAEA,QAAM,cAAc,YAAY,QAAQ,eAAe;AAGvD,QAAM,WAAW,YAAY,kBAAkB,CAAC;AAEhD,MAAI,CAAC;AAAU,UAAM,IAAI,MAAM,0CAA0C;AAGzE,QAAM,oBAAoB;AAAA,IACtB,WAAW,YAAY,QAAQ;AAAA,IAC/B,sBAAsB,wBAAwB,MAAM,MAAM;AAAA;AAAA,EAC9D;AAEA,QAAM,eAAe,YAAY,QAAQ,qBAAqB;AAAA,IAAI,iBAC9D,mBAAmB,YAAY,SAAS,aAAa,WAAW;AAAA,EACpE;AAEA,QAAM,aAAa,kBAAkB,aAAa,YAAY,iBAAiB;AAE/E,SAAO;AAAA,IACH,kBAAkB,EAAE,SAAS,YAAY,QAAQ,CAAC;AAAA,IAClD,QAAM,uBAAuB,SAAS,SAAS,GAA2B,EAAE;AAAA,IAC5E,QAAM,qCAAqC,mBAAmB,EAAE;AAAA,IAChE,QACI,aAAa,OAAO,CAAC,KAAK,gBAAgB;AACtC,aAAO,6BAA6B,aAAa,GAAG;AAAA,IACxD,GAAG,EAAE;AAAA,IACT,QAAO,YAAY,WAAW,SAAS,EAAE,GAAG,IAAI,WAAW,IAAI;AAAA,EACnE;AACJ","sourcesContent":["import type { Base58EncodedAddress } from '@solana/addresses';\nimport { pipe } from '@solana/functional';\nimport type { IAccountMeta, IInstruction } from '@solana/instructions';\nimport { AccountRole } from '@solana/instructions';\nimport type { Ed25519Signature } from '@solana/keys';\nimport type {\n Blockhash,\n ITransactionWithBlockhashLifetime,\n ITransactionWithFeePayer,\n ITransactionWithSignatures,\n Transaction,\n} from '@solana/transactions';\nimport {\n appendTransactionInstruction,\n createTransaction,\n setTransactionFeePayer,\n setTransactionLifetimeUsingBlockhash,\n} from '@solana/transactions';\nimport type {\n MessageAccountKeys,\n MessageCompiledInstruction,\n PublicKey,\n VersionedMessage,\n VersionedTransaction,\n} from '@solana/web3.js';\n\nfunction convertAccount(\n message: VersionedMessage,\n accountKeys: MessageAccountKeys,\n accountIndex: number\n): IAccountMeta {\n const accountPublicKey = accountKeys.get(accountIndex);\n if (!accountPublicKey) {\n // TODO coded error\n throw new Error(`Could not find account address at index ${accountIndex}`);\n }\n const isSigner = message.isAccountSigner(accountIndex);\n const isWritable = message.isAccountWritable(accountIndex);\n\n const role = isSigner\n ? isWritable\n ? AccountRole.WRITABLE_SIGNER\n : AccountRole.READONLY_SIGNER\n : isWritable\n ? AccountRole.WRITABLE\n : AccountRole.READONLY;\n\n return {\n address: accountPublicKey.toBase58() as Base58EncodedAddress,\n role,\n };\n}\n\nfunction convertInstruction(\n message: VersionedMessage,\n accountKeys: MessageAccountKeys,\n instruction: MessageCompiledInstruction\n): IInstruction {\n const programAddressPublicKey = accountKeys.get(instruction.programIdIndex);\n if (!programAddressPublicKey) {\n // TODO coded error\n throw new Error(`Could not find program address at index ${instruction.programIdIndex}`);\n }\n\n const accounts = instruction.accountKeyIndexes.map(accountIndex =>\n convertAccount(message, accountKeys, accountIndex)\n );\n\n return {\n programAddress: programAddressPublicKey.toBase58() as Base58EncodedAddress,\n ...(accounts.length ? { accounts } : {}),\n ...(instruction.data.length ? { data: instruction.data } : {}),\n };\n}\n\nfunction convertSignatures(\n transaction: VersionedTransaction,\n staticAccountKeys: PublicKey[]\n): ITransactionWithSignatures['signatures'] {\n return transaction.signatures.reduce((acc, sig, index) => {\n // legacy web3js includes a fake all 0 signature if it hasn't been signed\n // we don't do that for the new tx model. So just skip if it's all 0s\n const allZeros = sig.every(byte => byte === 0);\n if (allZeros) return acc;\n\n const address = staticAccountKeys[index].toBase58() as Base58EncodedAddress;\n return { ...acc, [address]: sig as Ed25519Signature };\n }, {});\n}\n\nexport function fromVersionedTransactionWithBlockhash(\n transaction: VersionedTransaction,\n lastValidBlockHeight?: bigint\n): Transaction & ITransactionWithFeePayer & ITransactionWithBlockhashLifetime {\n // TODO: add support for address table lookups\n // - will need to take `AddressLookupTableAccounts[]` as input\n // - will need to convert account instructions to `IAccountLookupMeta` when appropriate\n if (transaction.message.addressTableLookups.length > 0) {\n // TODO coded error\n throw new Error('Cannot convert transaction with addressTableLookups');\n }\n\n const accountKeys = transaction.message.getAccountKeys();\n\n // Fee payer is first account\n const feePayer = accountKeys.staticAccountKeys[0];\n // TODO: coded error\n if (!feePayer) throw new Error('No fee payer set in VersionedTransaction');\n\n // TOOD: add support for durable nonce transactions\n const blockhashLifetime = {\n blockhash: transaction.message.recentBlockhash as Blockhash,\n lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n, // U64 MAX\n };\n\n const instructions = transaction.message.compiledInstructions.map(instruction =>\n convertInstruction(transaction.message, accountKeys, instruction)\n );\n\n const signatures = convertSignatures(transaction, accountKeys.staticAccountKeys);\n\n return pipe(\n createTransaction({ version: transaction.version }),\n tx => setTransactionFeePayer(feePayer.toBase58() as Base58EncodedAddress, tx),\n tx => setTransactionLifetimeUsingBlockhash(blockhashLifetime, tx),\n tx =>\n instructions.reduce((acc, instruction) => {\n return appendTransactionInstruction(instruction, acc);\n }, tx),\n tx => (transaction.signatures.length ? { ...tx, signatures } : tx)\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/address.ts","../src/keypair.ts","../../codecs-core/dist/index.browser.js","../../codecs-strings/dist/index.browser.js","../../addresses/src/address.ts","../src/transaction.ts"],"names":["e"],"mappings":"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","sourcesContent":["import { Address } from '@solana/addresses';\nimport { PublicKey } from '@solana/web3.js';\n\n/**\n * Convert from a Legacy Web3 JS PublicKey to a base58 encoded address\n * @param publicKey The PublicKey to convert\n * @returns An Address\n */\nexport function fromLegacyPublicKey<TAddress extends string>(publicKey: PublicKey): Address<TAddress> {\n return publicKey.toBase58() as Address<TAddress>;\n}\n","import { createPrivateKeyFromBytes } from '@solana/keys';\nimport { Keypair } from '@solana/web3.js';\n\n/**\n * Convert from a Legacy Web3 JS Keypair to a CryptoKeyPair\n * @param keypair The Keypair to convert\n * @returns A CryptoKeyPair\n */\nexport async function fromLegacyKeypair(keypair: Keypair, extractable?: boolean): Promise<CryptoKeyPair> {\n const [publicKey, privateKey] = await Promise.all([\n crypto.subtle.importKey('raw', keypair.publicKey.toBytes(), 'Ed25519', true, ['verify']),\n createPrivateKeyFromBytes(keypair.secretKey.slice(0, 32), extractable),\n ]);\n return {\n privateKey,\n publicKey,\n } as CryptoKeyPair;\n}\n","// src/assertions.ts\nfunction assertByteArrayIsNotEmptyForCodec(codecDescription, bytes, offset = 0) {\n if (bytes.length - offset <= 0) {\n throw new Error(`Codec [${codecDescription}] cannot decode empty byte arrays.`);\n }\n}\nfunction assertByteArrayHasEnoughBytesForCodec(codecDescription, expected, bytes, offset = 0) {\n const bytesLength = bytes.length - offset;\n if (bytesLength < expected) {\n throw new Error(`Codec [${codecDescription}] expected ${expected} bytes, got ${bytesLength}.`);\n }\n}\n\n// src/bytes.ts\nvar mergeBytes = (byteArrays) => {\n const nonEmptyByteArrays = byteArrays.filter((arr) => arr.length);\n if (nonEmptyByteArrays.length === 0) {\n return byteArrays.length ? byteArrays[0] : new Uint8Array();\n }\n if (nonEmptyByteArrays.length === 1) {\n return nonEmptyByteArrays[0];\n }\n const totalLength = nonEmptyByteArrays.reduce((total, arr) => total + arr.length, 0);\n const result = new Uint8Array(totalLength);\n let offset = 0;\n nonEmptyByteArrays.forEach((arr) => {\n result.set(arr, offset);\n offset += arr.length;\n });\n return result;\n};\nvar padBytes = (bytes, length) => {\n if (bytes.length >= length)\n return bytes;\n const paddedBytes = new Uint8Array(length).fill(0);\n paddedBytes.set(bytes);\n return paddedBytes;\n};\nvar fixBytes = (bytes, length) => padBytes(bytes.length <= length ? bytes : bytes.slice(0, length), length);\n\n// src/codec.ts\nfunction getEncodedSize(value, encoder) {\n return \"fixedSize\" in encoder ? encoder.fixedSize : encoder.getSizeFromValue(value);\n}\nfunction createEncoder(encoder) {\n return Object.freeze({\n ...encoder,\n encode: (value) => {\n const bytes = new Uint8Array(getEncodedSize(value, encoder));\n encoder.write(value, bytes, 0);\n return bytes;\n }\n });\n}\nfunction createDecoder(decoder) {\n return Object.freeze({\n ...decoder,\n decode: (bytes, offset = 0) => decoder.read(bytes, offset)[0]\n });\n}\nfunction createCodec(codec) {\n return Object.freeze({\n ...codec,\n decode: (bytes, offset = 0) => codec.read(bytes, offset)[0],\n encode: (value) => {\n const bytes = new Uint8Array(getEncodedSize(value, codec));\n codec.write(value, bytes, 0);\n return bytes;\n }\n });\n}\nfunction isFixedSize(codec) {\n return \"fixedSize\" in codec && typeof codec.fixedSize === \"number\";\n}\nfunction assertIsFixedSize(codec, message) {\n if (!isFixedSize(codec)) {\n throw new Error(message ?? \"Expected a fixed-size codec, got a variable-size one.\");\n }\n}\nfunction isVariableSize(codec) {\n return !isFixedSize(codec);\n}\nfunction assertIsVariableSize(codec, message) {\n if (!isVariableSize(codec)) {\n throw new Error(message ?? \"Expected a variable-size codec, got a fixed-size one.\");\n }\n}\n\n// src/combine-codec.ts\nfunction combineCodec(encoder, decoder) {\n if (isFixedSize(encoder) !== isFixedSize(decoder)) {\n throw new Error(`Encoder and decoder must either both be fixed-size or variable-size.`);\n }\n if (isFixedSize(encoder) && isFixedSize(decoder) && encoder.fixedSize !== decoder.fixedSize) {\n throw new Error(\n `Encoder and decoder must have the same fixed size, got [${encoder.fixedSize}] and [${decoder.fixedSize}].`\n );\n }\n if (!isFixedSize(encoder) && !isFixedSize(decoder) && encoder.maxSize !== decoder.maxSize) {\n throw new Error(\n `Encoder and decoder must have the same max size, got [${encoder.maxSize}] and [${decoder.maxSize}].`\n );\n }\n return {\n ...decoder,\n ...encoder,\n decode: decoder.decode,\n encode: encoder.encode,\n read: decoder.read,\n write: encoder.write\n };\n}\n\n// src/fix-codec.ts\nfunction fixEncoder(encoder, fixedBytes) {\n return createEncoder({\n fixedSize: fixedBytes,\n write: (value, bytes, offset) => {\n const variableByteArray = encoder.encode(value);\n const fixedByteArray = variableByteArray.length > fixedBytes ? variableByteArray.slice(0, fixedBytes) : variableByteArray;\n bytes.set(fixedByteArray, offset);\n return offset + fixedBytes;\n }\n });\n}\nfunction fixDecoder(decoder, fixedBytes) {\n return createDecoder({\n fixedSize: fixedBytes,\n read: (bytes, offset) => {\n assertByteArrayHasEnoughBytesForCodec(\"fixCodec\", fixedBytes, bytes, offset);\n if (offset > 0 || bytes.length > fixedBytes) {\n bytes = bytes.slice(offset, offset + fixedBytes);\n }\n if (isFixedSize(decoder)) {\n bytes = fixBytes(bytes, decoder.fixedSize);\n }\n const [value] = decoder.read(bytes, 0);\n return [value, offset + fixedBytes];\n }\n });\n}\nfunction fixCodec(codec, fixedBytes) {\n return combineCodec(fixEncoder(codec, fixedBytes), fixDecoder(codec, fixedBytes));\n}\n\n// src/map-codec.ts\nfunction mapEncoder(encoder, unmap) {\n return createEncoder({\n ...isVariableSize(encoder) ? { ...encoder, getSizeFromValue: (value) => encoder.getSizeFromValue(unmap(value)) } : encoder,\n write: (value, bytes, offset) => encoder.write(unmap(value), bytes, offset)\n });\n}\nfunction mapDecoder(decoder, map) {\n return createDecoder({\n ...decoder,\n read: (bytes, offset) => {\n const [value, newOffset] = decoder.read(bytes, offset);\n return [map(value, bytes, offset), newOffset];\n }\n });\n}\nfunction mapCodec(codec, unmap, map) {\n return createCodec({\n ...mapEncoder(codec, unmap),\n read: map ? mapDecoder(codec, map).read : codec.read\n });\n}\n\n// src/reverse-codec.ts\nfunction reverseEncoder(encoder) {\n assertIsFixedSize(encoder, \"Cannot reverse a codec of variable size.\");\n return createEncoder({\n ...encoder,\n write: (value, bytes, offset) => {\n const newOffset = encoder.write(value, bytes, offset);\n const slice = bytes.slice(offset, offset + encoder.fixedSize).reverse();\n bytes.set(slice, offset);\n return newOffset;\n }\n });\n}\nfunction reverseDecoder(decoder) {\n assertIsFixedSize(decoder, \"Cannot reverse a codec of variable size.\");\n return createDecoder({\n ...decoder,\n read: (bytes, offset) => {\n const reverseEnd = offset + decoder.fixedSize;\n if (offset === 0 && bytes.length === reverseEnd) {\n return decoder.read(bytes.reverse(), offset);\n }\n const reversedBytes = bytes.slice();\n reversedBytes.set(bytes.slice(offset, reverseEnd).reverse(), offset);\n return decoder.read(reversedBytes, offset);\n }\n });\n}\nfunction reverseCodec(codec) {\n return combineCodec(reverseEncoder(codec), reverseDecoder(codec));\n}\n\nexport { assertByteArrayHasEnoughBytesForCodec, assertByteArrayIsNotEmptyForCodec, assertIsFixedSize, assertIsVariableSize, combineCodec, createCodec, createDecoder, createEncoder, fixBytes, fixCodec, fixDecoder, fixEncoder, getEncodedSize, isFixedSize, isVariableSize, mapCodec, mapDecoder, mapEncoder, mergeBytes, padBytes, reverseCodec, reverseDecoder, reverseEncoder };\n","import { createEncoder, createDecoder, combineCodec, fixEncoder, getEncodedSize, fixDecoder, assertByteArrayIsNotEmptyForCodec, assertByteArrayHasEnoughBytesForCodec } from '@solana/codecs-core';\nimport { getU32Encoder, getU32Decoder } from '@solana/codecs-numbers';\n\n// src/assertions.ts\nfunction assertValidBaseString(alphabet4, testValue, givenValue = testValue) {\n if (!testValue.match(new RegExp(`^[${alphabet4}]*$`))) {\n throw new Error(`Expected a string of base ${alphabet4.length}, got [${givenValue}].`);\n }\n}\nvar getBaseXEncoder = (alphabet4) => {\n return createEncoder({\n getSizeFromValue: (value) => {\n const [leadingZeroes, tailChars] = partitionLeadingZeroes(value, alphabet4[0]);\n if (tailChars === \"\")\n return value.length;\n const base10Number = getBigIntFromBaseX(tailChars, alphabet4);\n return leadingZeroes.length + Math.ceil(base10Number.toString(16).length / 2);\n },\n write(value, bytes, offset) {\n assertValidBaseString(alphabet4, value);\n if (value === \"\")\n return offset;\n const [leadingZeroes, tailChars] = partitionLeadingZeroes(value, alphabet4[0]);\n if (tailChars === \"\") {\n bytes.set(new Uint8Array(leadingZeroes.length).fill(0), offset);\n return offset + leadingZeroes.length;\n }\n let base10Number = getBigIntFromBaseX(tailChars, alphabet4);\n const tailBytes = [];\n while (base10Number > 0n) {\n tailBytes.unshift(Number(base10Number % 256n));\n base10Number /= 256n;\n }\n const bytesToAdd = [...Array(leadingZeroes.length).fill(0), ...tailBytes];\n bytes.set(bytesToAdd, offset);\n return offset + bytesToAdd.length;\n }\n });\n};\nvar getBaseXDecoder = (alphabet4) => {\n return createDecoder({\n read(rawBytes, offset) {\n const bytes = offset === 0 ? rawBytes : rawBytes.slice(offset);\n if (bytes.length === 0)\n return [\"\", 0];\n let trailIndex = bytes.findIndex((n) => n !== 0);\n trailIndex = trailIndex === -1 ? bytes.length : trailIndex;\n const leadingZeroes = alphabet4[0].repeat(trailIndex);\n if (trailIndex === bytes.length)\n return [leadingZeroes, rawBytes.length];\n const base10Number = bytes.slice(trailIndex).reduce((sum, byte) => sum * 256n + BigInt(byte), 0n);\n const tailChars = getBaseXFromBigInt(base10Number, alphabet4);\n return [leadingZeroes + tailChars, rawBytes.length];\n }\n });\n};\nvar getBaseXCodec = (alphabet4) => combineCodec(getBaseXEncoder(alphabet4), getBaseXDecoder(alphabet4));\nfunction partitionLeadingZeroes(value, zeroCharacter) {\n const leadingZeroIndex = [...value].findIndex((c) => c !== zeroCharacter);\n return leadingZeroIndex === -1 ? [value, \"\"] : [value.slice(0, leadingZeroIndex), value.slice(leadingZeroIndex)];\n}\nfunction getBigIntFromBaseX(value, alphabet4) {\n const base = BigInt(alphabet4.length);\n return [...value].reduce((sum, char) => sum * base + BigInt(alphabet4.indexOf(char)), 0n);\n}\nfunction getBaseXFromBigInt(value, alphabet4) {\n const base = BigInt(alphabet4.length);\n const tailChars = [];\n while (value > 0n) {\n tailChars.unshift(alphabet4[Number(value % base)]);\n value /= base;\n }\n return tailChars.join(\"\");\n}\n\n// src/base10.ts\nvar alphabet = \"0123456789\";\nvar getBase10Encoder = () => getBaseXEncoder(alphabet);\nvar getBase10Decoder = () => getBaseXDecoder(alphabet);\nvar getBase10Codec = () => getBaseXCodec(alphabet);\nvar getBase16Encoder = () => createEncoder({\n getSizeFromValue: (value) => Math.ceil(value.length / 2),\n write(value, bytes, offset) {\n const lowercaseValue = value.toLowerCase();\n assertValidBaseString(\"0123456789abcdef\", lowercaseValue, value);\n const matches = lowercaseValue.match(/.{1,2}/g);\n const hexBytes = matches ? matches.map((byte) => parseInt(byte, 16)) : [];\n bytes.set(hexBytes, offset);\n return hexBytes.length + offset;\n }\n});\nvar getBase16Decoder = () => createDecoder({\n read(bytes, offset) {\n const value = bytes.slice(offset).reduce((str, byte) => str + byte.toString(16).padStart(2, \"0\"), \"\");\n return [value, bytes.length];\n }\n});\nvar getBase16Codec = () => combineCodec(getBase16Encoder(), getBase16Decoder());\n\n// src/base58.ts\nvar alphabet2 = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\nvar getBase58Encoder = () => getBaseXEncoder(alphabet2);\nvar getBase58Decoder = () => getBaseXDecoder(alphabet2);\nvar getBase58Codec = () => getBaseXCodec(alphabet2);\nvar getBaseXResliceEncoder = (alphabet4, bits) => createEncoder({\n getSizeFromValue: (value) => Math.floor(value.length * bits / 8),\n write(value, bytes, offset) {\n assertValidBaseString(alphabet4, value);\n if (value === \"\")\n return offset;\n const charIndices = [...value].map((c) => alphabet4.indexOf(c));\n const reslicedBytes = reslice(charIndices, bits, 8, false);\n bytes.set(reslicedBytes, offset);\n return reslicedBytes.length + offset;\n }\n});\nvar getBaseXResliceDecoder = (alphabet4, bits) => createDecoder({\n read(rawBytes, offset = 0) {\n const bytes = offset === 0 ? rawBytes : rawBytes.slice(offset);\n if (bytes.length === 0)\n return [\"\", rawBytes.length];\n const charIndices = reslice([...bytes], 8, bits, true);\n return [charIndices.map((i) => alphabet4[i]).join(\"\"), rawBytes.length];\n }\n});\nvar getBaseXResliceCodec = (alphabet4, bits) => combineCodec(getBaseXResliceEncoder(alphabet4, bits), getBaseXResliceDecoder(alphabet4, bits));\nfunction reslice(input, inputBits, outputBits, useRemainder) {\n const output = [];\n let accumulator = 0;\n let bitsInAccumulator = 0;\n const mask = (1 << outputBits) - 1;\n for (const value of input) {\n accumulator = accumulator << inputBits | value;\n bitsInAccumulator += inputBits;\n while (bitsInAccumulator >= outputBits) {\n bitsInAccumulator -= outputBits;\n output.push(accumulator >> bitsInAccumulator & mask);\n }\n }\n if (useRemainder && bitsInAccumulator > 0) {\n output.push(accumulator << outputBits - bitsInAccumulator & mask);\n }\n return output;\n}\nvar getBase64Encoder = () => {\n {\n return createEncoder({\n getSizeFromValue: (value) => {\n try {\n return atob(value).length;\n } catch (e2) {\n throw new Error(`Expected a string of base 64, got [${value}].`);\n }\n },\n write(value, bytes, offset) {\n try {\n const bytesToAdd = atob(value).split(\"\").map((c) => c.charCodeAt(0));\n bytes.set(bytesToAdd, offset);\n return bytesToAdd.length + offset;\n } catch (e2) {\n throw new Error(`Expected a string of base 64, got [${value}].`);\n }\n }\n });\n }\n};\nvar getBase64Decoder = () => {\n {\n return createDecoder({\n read(bytes, offset = 0) {\n const slice = bytes.slice(offset);\n const value = btoa(String.fromCharCode(...slice));\n return [value, bytes.length];\n }\n });\n }\n};\nvar getBase64Codec = () => combineCodec(getBase64Encoder(), getBase64Decoder());\n\n// src/null-characters.ts\nvar removeNullCharacters = (value) => (\n // eslint-disable-next-line no-control-regex\n value.replace(/\\u0000/g, \"\")\n);\nvar padNullCharacters = (value, chars) => value.padEnd(chars, \"\\0\");\n\n// ../text-encoding-impl/dist/index.browser.js\nvar e = globalThis.TextDecoder;\nvar o = globalThis.TextEncoder;\n\n// src/utf8.ts\nvar getUtf8Encoder = () => {\n let textEncoder;\n return createEncoder({\n getSizeFromValue: (value) => (textEncoder ||= new o()).encode(value).length,\n write: (value, bytes, offset) => {\n const bytesToAdd = (textEncoder ||= new o()).encode(value);\n bytes.set(bytesToAdd, offset);\n return offset + bytesToAdd.length;\n }\n });\n};\nvar getUtf8Decoder = () => {\n let textDecoder;\n return createDecoder({\n read(bytes, offset) {\n const value = (textDecoder ||= new e()).decode(bytes.slice(offset));\n return [removeNullCharacters(value), bytes.length];\n }\n });\n};\nvar getUtf8Codec = () => combineCodec(getUtf8Encoder(), getUtf8Decoder());\n\n// src/string.ts\nfunction getStringEncoder(config = {}) {\n const size = config.size ?? getU32Encoder();\n const encoding = config.encoding ?? getUtf8Encoder();\n if (size === \"variable\") {\n return encoding;\n }\n if (typeof size === \"number\") {\n return fixEncoder(encoding, size);\n }\n return createEncoder({\n getSizeFromValue: (value) => {\n const contentSize = getEncodedSize(value, encoding);\n return getEncodedSize(contentSize, size) + contentSize;\n },\n write: (value, bytes, offset) => {\n const contentSize = getEncodedSize(value, encoding);\n offset = size.write(contentSize, bytes, offset);\n return encoding.write(value, bytes, offset);\n }\n });\n}\nfunction getStringDecoder(config = {}) {\n const size = config.size ?? getU32Decoder();\n const encoding = config.encoding ?? getUtf8Decoder();\n if (size === \"variable\") {\n return encoding;\n }\n if (typeof size === \"number\") {\n return fixDecoder(encoding, size);\n }\n return createDecoder({\n read: (bytes, offset = 0) => {\n assertByteArrayIsNotEmptyForCodec(\"string\", bytes, offset);\n const [lengthBigInt, lengthOffset] = size.read(bytes, offset);\n const length = Number(lengthBigInt);\n offset = lengthOffset;\n const contentBytes = bytes.slice(offset, offset + length);\n assertByteArrayHasEnoughBytesForCodec(\"string\", length, contentBytes);\n const [value, contentOffset] = encoding.read(contentBytes, 0);\n offset += contentOffset;\n return [value, offset];\n }\n });\n}\nfunction getStringCodec(config = {}) {\n return combineCodec(getStringEncoder(config), getStringDecoder(config));\n}\n\nexport { assertValidBaseString, getBase10Codec, getBase10Decoder, getBase10Encoder, getBase16Codec, getBase16Decoder, getBase16Encoder, getBase58Codec, getBase58Decoder, getBase58Encoder, getBase64Codec, getBase64Decoder, getBase64Encoder, getBaseXCodec, getBaseXDecoder, getBaseXEncoder, getBaseXResliceCodec, getBaseXResliceDecoder, getBaseXResliceEncoder, getStringCodec, getStringDecoder, getStringEncoder, getUtf8Codec, getUtf8Decoder, getUtf8Encoder, padNullCharacters, removeNullCharacters };\n","import {\n combineCodec,\n Decoder,\n Encoder,\n FixedSizeCodec,\n FixedSizeDecoder,\n FixedSizeEncoder,\n mapEncoder,\n} from '@solana/codecs-core';\nimport { getBase58Decoder, getBase58Encoder, getStringDecoder, getStringEncoder } from '@solana/codecs-strings';\n\nexport type Address<TAddress extends string = string> = TAddress & {\n readonly __brand: unique symbol;\n};\n\nlet memoizedBase58Encoder: Encoder<string> | undefined;\nlet memoizedBase58Decoder: Decoder<string> | undefined;\n\nfunction getMemoizedBase58Encoder(): Encoder<string> {\n if (!memoizedBase58Encoder) memoizedBase58Encoder = getBase58Encoder();\n return memoizedBase58Encoder;\n}\n\nfunction getMemoizedBase58Decoder(): Decoder<string> {\n if (!memoizedBase58Decoder) memoizedBase58Decoder = getBase58Decoder();\n return memoizedBase58Decoder;\n}\n\nexport function isAddress(putativeAddress: string): putativeAddress is Address<typeof putativeAddress> {\n // Fast-path; see if the input string is of an acceptable length.\n if (\n // Lowest address (32 bytes of zeroes)\n putativeAddress.length < 32 ||\n // Highest address (32 bytes of 255)\n putativeAddress.length > 44\n ) {\n return false;\n }\n // Slow-path; actually attempt to decode the input string.\n const base58Encoder = getMemoizedBase58Encoder();\n const bytes = base58Encoder.encode(putativeAddress);\n const numBytes = bytes.byteLength;\n if (numBytes !== 32) {\n return false;\n }\n return true;\n}\n\nexport function assertIsAddress(putativeAddress: string): asserts putativeAddress is Address<typeof putativeAddress> {\n try {\n // Fast-path; see if the input string is of an acceptable length.\n if (\n // Lowest address (32 bytes of zeroes)\n putativeAddress.length < 32 ||\n // Highest address (32 bytes of 255)\n putativeAddress.length > 44\n ) {\n throw new Error('Expected input string to decode to a byte array of length 32.');\n }\n // Slow-path; actually attempt to decode the input string.\n const base58Encoder = getMemoizedBase58Encoder();\n const bytes = base58Encoder.encode(putativeAddress);\n const numBytes = bytes.byteLength;\n if (numBytes !== 32) {\n throw new Error(`Expected input string to decode to a byte array of length 32. Actual length: ${numBytes}`);\n }\n } catch (e) {\n throw new Error(`\\`${putativeAddress}\\` is not a base-58 encoded address`, {\n cause: e,\n });\n }\n}\n\nexport function address<TAddress extends string = string>(putativeAddress: TAddress): Address<TAddress> {\n assertIsAddress(putativeAddress);\n return putativeAddress as Address<TAddress>;\n}\n\nexport function getAddressEncoder(): FixedSizeEncoder<Address, 32> {\n return mapEncoder(getStringEncoder({ encoding: getMemoizedBase58Encoder(), size: 32 }), putativeAddress =>\n address(putativeAddress),\n );\n}\n\nexport function getAddressDecoder(): FixedSizeDecoder<Address, 32> {\n return getStringDecoder({ encoding: getMemoizedBase58Decoder(), size: 32 }) as FixedSizeDecoder<Address, 32>;\n}\n\nexport function getAddressCodec(): FixedSizeCodec<Address, Address, 32> {\n return combineCodec(getAddressEncoder(), getAddressDecoder());\n}\n\nexport function getAddressComparator(): (x: string, y: string) => number {\n return new Intl.Collator('en', {\n caseFirst: 'lower',\n ignorePunctuation: false,\n localeMatcher: 'best fit',\n numeric: false,\n sensitivity: 'variant',\n usage: 'sort',\n }).compare;\n}\n","import { type Address, assertIsAddress } from '@solana/addresses';\nimport { pipe } from '@solana/functional';\nimport type { IAccountMeta, IInstruction } from '@solana/instructions';\nimport { AccountRole } from '@solana/instructions';\nimport type { SignatureBytes } from '@solana/keys';\nimport {\n appendTransactionInstruction,\n type Blockhash,\n createTransaction,\n type IDurableNonceTransaction,\n isAdvanceNonceAccountInstruction,\n type ITransactionWithBlockhashLifetime,\n type ITransactionWithFeePayer,\n type ITransactionWithSignatures,\n type Nonce,\n setTransactionFeePayer,\n setTransactionLifetimeUsingBlockhash,\n setTransactionLifetimeUsingDurableNonce,\n type Transaction,\n} from '@solana/transactions';\nimport type {\n MessageAccountKeys,\n MessageCompiledInstruction,\n PublicKey,\n VersionedMessage,\n VersionedTransaction,\n} from '@solana/web3.js';\n\nfunction convertAccount(\n message: VersionedMessage,\n accountKeys: MessageAccountKeys,\n accountIndex: number,\n): IAccountMeta {\n const accountPublicKey = accountKeys.get(accountIndex);\n if (!accountPublicKey) {\n // TODO coded error\n throw new Error(`Could not find account address at index ${accountIndex}`);\n }\n const isSigner = message.isAccountSigner(accountIndex);\n const isWritable = message.isAccountWritable(accountIndex);\n\n const role = isSigner\n ? isWritable\n ? AccountRole.WRITABLE_SIGNER\n : AccountRole.READONLY_SIGNER\n : isWritable\n ? AccountRole.WRITABLE\n : AccountRole.READONLY;\n\n return {\n address: accountPublicKey.toBase58() as Address,\n role,\n };\n}\n\nfunction convertInstruction(\n message: VersionedMessage,\n accountKeys: MessageAccountKeys,\n instruction: MessageCompiledInstruction,\n): IInstruction {\n const programAddressPublicKey = accountKeys.get(instruction.programIdIndex);\n if (!programAddressPublicKey) {\n // TODO coded error\n throw new Error(`Could not find program address at index ${instruction.programIdIndex}`);\n }\n\n const accounts = instruction.accountKeyIndexes.map(accountIndex =>\n convertAccount(message, accountKeys, accountIndex),\n );\n\n return {\n programAddress: programAddressPublicKey.toBase58() as Address,\n ...(accounts.length ? { accounts } : {}),\n ...(instruction.data.length ? { data: instruction.data } : {}),\n };\n}\n\nfunction convertSignatures(\n transaction: VersionedTransaction,\n staticAccountKeys: PublicKey[],\n): ITransactionWithSignatures['signatures'] {\n return transaction.signatures.reduce((acc, sig, index) => {\n // legacy web3js includes a fake all 0 signature if it hasn't been signed\n // we don't do that for the new tx model. So just skip if it's all 0s\n const allZeros = sig.every(byte => byte === 0);\n if (allZeros) return acc;\n\n const address = staticAccountKeys[index].toBase58() as Address;\n return { ...acc, [address]: sig as SignatureBytes };\n }, {});\n}\n\nexport function fromVersionedTransactionWithBlockhash(\n transaction: VersionedTransaction,\n lastValidBlockHeight?: bigint,\n): Transaction & ITransactionWithFeePayer & ITransactionWithBlockhashLifetime {\n // TODO: add support for address table lookups\n // - will need to take `AddressLookupTableAccounts[]` as input\n // - will need to convert account instructions to `IAccountLookupMeta` when appropriate\n if (transaction.message.addressTableLookups.length > 0) {\n // TODO coded error\n throw new Error('Cannot convert transaction with addressTableLookups');\n }\n\n const accountKeys = transaction.message.getAccountKeys();\n\n // Fee payer is first account\n const feePayer = accountKeys.staticAccountKeys[0];\n // TODO: coded error\n if (!feePayer) throw new Error('No fee payer set in VersionedTransaction');\n\n const blockhashLifetime = {\n blockhash: transaction.message.recentBlockhash as Blockhash,\n lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n, // U64 MAX\n };\n\n const instructions = transaction.message.compiledInstructions.map(instruction =>\n convertInstruction(transaction.message, accountKeys, instruction),\n );\n\n const signatures = convertSignatures(transaction, accountKeys.staticAccountKeys);\n\n return pipe(\n createTransaction({ version: transaction.version }),\n tx => setTransactionFeePayer(feePayer.toBase58() as Address, tx),\n tx => setTransactionLifetimeUsingBlockhash(blockhashLifetime, tx),\n tx =>\n instructions.reduce((acc, instruction) => {\n return appendTransactionInstruction(instruction, acc);\n }, tx),\n tx => (transaction.signatures.length ? { ...tx, signatures } : tx),\n );\n}\n\nexport function fromVersionedTransactionWithDurableNonce(\n transaction: VersionedTransaction,\n): Transaction & ITransactionWithFeePayer & IDurableNonceTransaction {\n // TODO: add support for address table lookups\n // - will need to take `AddressLookupTableAccounts[]` as input\n // - will need to convert account instructions to `IAccountLookupMeta` when appropriate\n if (transaction.message.addressTableLookups.length > 0) {\n // TODO coded error\n throw new Error('Cannot convert transaction with addressTableLookups');\n }\n\n const accountKeys = transaction.message.getAccountKeys();\n\n // Fee payer is first account\n const feePayer = accountKeys.staticAccountKeys[0];\n // TODO: coded error\n if (!feePayer) throw new Error('No fee payer set in VersionedTransaction');\n\n const instructions = transaction.message.compiledInstructions.map(instruction =>\n convertInstruction(transaction.message, accountKeys, instruction),\n );\n\n // Check first instruction is durable nonce + extract params\n if (instructions.length === 0) {\n // TODO: coded error\n throw new Error('transaction with no instructions cannot be durable nonce transaction');\n }\n\n if (!isAdvanceNonceAccountInstruction(instructions[0])) {\n // TODO: coded error\n throw new Error('transaction first instruction is not advance nonce account instruction');\n }\n\n // We know these accounts are defined because we checked `isAdvanceNonceAccountInstruction`\n const nonceAccountAddress = instructions[0].accounts![0].address;\n assertIsAddress(nonceAccountAddress);\n\n const nonceAuthorityAddress = instructions[0].accounts![2].address;\n assertIsAddress(nonceAuthorityAddress);\n\n const durableNonceLifetime = {\n nonce: transaction.message.recentBlockhash as Nonce,\n nonceAccountAddress,\n nonceAuthorityAddress,\n };\n\n const signatures = convertSignatures(transaction, accountKeys.staticAccountKeys);\n\n return pipe(\n createTransaction({ version: transaction.version }),\n tx => setTransactionFeePayer(feePayer.toBase58() as Address, tx),\n tx => setTransactionLifetimeUsingDurableNonce(durableNonceLifetime, tx),\n tx =>\n instructions.slice(1).reduce((acc, instruction) => {\n return appendTransactionInstruction(instruction, acc);\n }, tx),\n tx => (transaction.signatures.length ? { ...tx, signatures } : tx),\n );\n}\n"]}
@@ -1,8 +1,113 @@
1
+ import { createPrivateKeyFromBytes } from '@solana/keys';
1
2
  import { pipe } from '@solana/functional';
2
3
  import { AccountRole } from '@solana/instructions';
3
- import { createTransaction, setTransactionFeePayer, setTransactionLifetimeUsingBlockhash, appendTransactionInstruction } from '@solana/transactions';
4
+ import { createTransaction, setTransactionFeePayer, setTransactionLifetimeUsingBlockhash, appendTransactionInstruction, isAdvanceNonceAccountInstruction, setTransactionLifetimeUsingDurableNonce } from '@solana/transactions';
4
5
 
5
- // src/transaction.ts
6
+ // src/address.ts
7
+ function fromLegacyPublicKey(publicKey) {
8
+ return publicKey.toBase58();
9
+ }
10
+ async function fromLegacyKeypair(keypair, extractable) {
11
+ const [publicKey, privateKey] = await Promise.all([
12
+ crypto.subtle.importKey("raw", keypair.publicKey.toBytes(), "Ed25519", true, ["verify"]),
13
+ createPrivateKeyFromBytes(keypair.secretKey.slice(0, 32), extractable)
14
+ ]);
15
+ return {
16
+ privateKey,
17
+ publicKey
18
+ };
19
+ }
20
+
21
+ // ../codecs-core/dist/index.browser.js
22
+ function getEncodedSize(value, encoder) {
23
+ return "fixedSize" in encoder ? encoder.fixedSize : encoder.getSizeFromValue(value);
24
+ }
25
+ function createEncoder(encoder) {
26
+ return Object.freeze({
27
+ ...encoder,
28
+ encode: (value) => {
29
+ const bytes = new Uint8Array(getEncodedSize(value, encoder));
30
+ encoder.write(value, bytes, 0);
31
+ return bytes;
32
+ }
33
+ });
34
+ }
35
+
36
+ // ../codecs-strings/dist/index.browser.js
37
+ function assertValidBaseString(alphabet4, testValue, givenValue = testValue) {
38
+ if (!testValue.match(new RegExp(`^[${alphabet4}]*$`))) {
39
+ throw new Error(`Expected a string of base ${alphabet4.length}, got [${givenValue}].`);
40
+ }
41
+ }
42
+ var getBaseXEncoder = (alphabet4) => {
43
+ return createEncoder({
44
+ getSizeFromValue: (value) => {
45
+ const [leadingZeroes, tailChars] = partitionLeadingZeroes(value, alphabet4[0]);
46
+ if (tailChars === "")
47
+ return value.length;
48
+ const base10Number = getBigIntFromBaseX(tailChars, alphabet4);
49
+ return leadingZeroes.length + Math.ceil(base10Number.toString(16).length / 2);
50
+ },
51
+ write(value, bytes, offset) {
52
+ assertValidBaseString(alphabet4, value);
53
+ if (value === "")
54
+ return offset;
55
+ const [leadingZeroes, tailChars] = partitionLeadingZeroes(value, alphabet4[0]);
56
+ if (tailChars === "") {
57
+ bytes.set(new Uint8Array(leadingZeroes.length).fill(0), offset);
58
+ return offset + leadingZeroes.length;
59
+ }
60
+ let base10Number = getBigIntFromBaseX(tailChars, alphabet4);
61
+ const tailBytes = [];
62
+ while (base10Number > 0n) {
63
+ tailBytes.unshift(Number(base10Number % 256n));
64
+ base10Number /= 256n;
65
+ }
66
+ const bytesToAdd = [...Array(leadingZeroes.length).fill(0), ...tailBytes];
67
+ bytes.set(bytesToAdd, offset);
68
+ return offset + bytesToAdd.length;
69
+ }
70
+ });
71
+ };
72
+ function partitionLeadingZeroes(value, zeroCharacter) {
73
+ const leadingZeroIndex = [...value].findIndex((c) => c !== zeroCharacter);
74
+ return leadingZeroIndex === -1 ? [value, ""] : [value.slice(0, leadingZeroIndex), value.slice(leadingZeroIndex)];
75
+ }
76
+ function getBigIntFromBaseX(value, alphabet4) {
77
+ const base = BigInt(alphabet4.length);
78
+ return [...value].reduce((sum, char) => sum * base + BigInt(alphabet4.indexOf(char)), 0n);
79
+ }
80
+ var alphabet2 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
81
+ var getBase58Encoder = () => getBaseXEncoder(alphabet2);
82
+
83
+ // ../addresses/dist/index.browser.js
84
+ var memoizedBase58Encoder;
85
+ function getMemoizedBase58Encoder() {
86
+ if (!memoizedBase58Encoder)
87
+ memoizedBase58Encoder = getBase58Encoder();
88
+ return memoizedBase58Encoder;
89
+ }
90
+ function assertIsAddress(putativeAddress) {
91
+ try {
92
+ if (
93
+ // Lowest address (32 bytes of zeroes)
94
+ putativeAddress.length < 32 || // Highest address (32 bytes of 255)
95
+ putativeAddress.length > 44
96
+ ) {
97
+ throw new Error("Expected input string to decode to a byte array of length 32.");
98
+ }
99
+ const base58Encoder = getMemoizedBase58Encoder();
100
+ const bytes = base58Encoder.encode(putativeAddress);
101
+ const numBytes = bytes.byteLength;
102
+ if (numBytes !== 32) {
103
+ throw new Error(`Expected input string to decode to a byte array of length 32. Actual length: ${numBytes}`);
104
+ }
105
+ } catch (e2) {
106
+ throw new Error(`\`${putativeAddress}\` is not a base-58 encoded address`, {
107
+ cause: e2
108
+ });
109
+ }
110
+ }
6
111
  function convertAccount(message, accountKeys, accountIndex) {
7
112
  const accountPublicKey = accountKeys.get(accountIndex);
8
113
  if (!accountPublicKey) {
@@ -66,7 +171,44 @@ function fromVersionedTransactionWithBlockhash(transaction, lastValidBlockHeight
66
171
  (tx) => transaction.signatures.length ? { ...tx, signatures } : tx
67
172
  );
68
173
  }
174
+ function fromVersionedTransactionWithDurableNonce(transaction) {
175
+ if (transaction.message.addressTableLookups.length > 0) {
176
+ throw new Error("Cannot convert transaction with addressTableLookups");
177
+ }
178
+ const accountKeys = transaction.message.getAccountKeys();
179
+ const feePayer = accountKeys.staticAccountKeys[0];
180
+ if (!feePayer)
181
+ throw new Error("No fee payer set in VersionedTransaction");
182
+ const instructions = transaction.message.compiledInstructions.map(
183
+ (instruction) => convertInstruction(transaction.message, accountKeys, instruction)
184
+ );
185
+ if (instructions.length === 0) {
186
+ throw new Error("transaction with no instructions cannot be durable nonce transaction");
187
+ }
188
+ if (!isAdvanceNonceAccountInstruction(instructions[0])) {
189
+ throw new Error("transaction first instruction is not advance nonce account instruction");
190
+ }
191
+ const nonceAccountAddress = instructions[0].accounts[0].address;
192
+ assertIsAddress(nonceAccountAddress);
193
+ const nonceAuthorityAddress = instructions[0].accounts[2].address;
194
+ assertIsAddress(nonceAuthorityAddress);
195
+ const durableNonceLifetime = {
196
+ nonce: transaction.message.recentBlockhash,
197
+ nonceAccountAddress,
198
+ nonceAuthorityAddress
199
+ };
200
+ const signatures = convertSignatures(transaction, accountKeys.staticAccountKeys);
201
+ return pipe(
202
+ createTransaction({ version: transaction.version }),
203
+ (tx) => setTransactionFeePayer(feePayer.toBase58(), tx),
204
+ (tx) => setTransactionLifetimeUsingDurableNonce(durableNonceLifetime, tx),
205
+ (tx) => instructions.slice(1).reduce((acc, instruction) => {
206
+ return appendTransactionInstruction(instruction, acc);
207
+ }, tx),
208
+ (tx) => transaction.signatures.length ? { ...tx, signatures } : tx
209
+ );
210
+ }
69
211
 
70
- export { fromVersionedTransactionWithBlockhash };
212
+ export { fromLegacyKeypair, fromLegacyPublicKey, fromVersionedTransactionWithBlockhash, fromVersionedTransactionWithDurableNonce };
71
213
  //# sourceMappingURL=out.js.map
72
214
  //# sourceMappingURL=index.browser.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/transaction.ts"],"names":[],"mappings":";AACA,SAAS,YAAY;AAErB,SAAS,mBAAmB;AAS5B;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACG;AASP,SAAS,eACL,SACA,aACA,cACY;AACZ,QAAM,mBAAmB,YAAY,IAAI,YAAY;AACrD,MAAI,CAAC,kBAAkB;AAEnB,UAAM,IAAI,MAAM,2CAA2C,YAAY,EAAE;AAAA,EAC7E;AACA,QAAM,WAAW,QAAQ,gBAAgB,YAAY;AACrD,QAAM,aAAa,QAAQ,kBAAkB,YAAY;AAEzD,QAAM,OAAO,WACP,aACI,YAAY,kBACZ,YAAY,kBAChB,aACA,YAAY,WACZ,YAAY;AAElB,SAAO;AAAA,IACH,SAAS,iBAAiB,SAAS;AAAA,IACnC;AAAA,EACJ;AACJ;AAEA,SAAS,mBACL,SACA,aACA,aACY;AACZ,QAAM,0BAA0B,YAAY,IAAI,YAAY,cAAc;AAC1E,MAAI,CAAC,yBAAyB;AAE1B,UAAM,IAAI,MAAM,2CAA2C,YAAY,cAAc,EAAE;AAAA,EAC3F;AAEA,QAAM,WAAW,YAAY,kBAAkB;AAAA,IAAI,kBAC/C,eAAe,SAAS,aAAa,YAAY;AAAA,EACrD;AAEA,SAAO;AAAA,IACH,gBAAgB,wBAAwB,SAAS;AAAA,IACjD,GAAI,SAAS,SAAS,EAAE,SAAS,IAAI,CAAC;AAAA,IACtC,GAAI,YAAY,KAAK,SAAS,EAAE,MAAM,YAAY,KAAK,IAAI,CAAC;AAAA,EAChE;AACJ;AAEA,SAAS,kBACL,aACA,mBACwC;AACxC,SAAO,YAAY,WAAW,OAAO,CAAC,KAAK,KAAK,UAAU;AAGtD,UAAM,WAAW,IAAI,MAAM,UAAQ,SAAS,CAAC;AAC7C,QAAI;AAAU,aAAO;AAErB,UAAM,UAAU,kBAAkB,KAAK,EAAE,SAAS;AAClD,WAAO,EAAE,GAAG,KAAK,CAAC,OAAO,GAAG,IAAwB;AAAA,EACxD,GAAG,CAAC,CAAC;AACT;AAEO,SAAS,sCACZ,aACA,sBAC0E;AAI1E,MAAI,YAAY,QAAQ,oBAAoB,SAAS,GAAG;AAEpD,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACzE;AAEA,QAAM,cAAc,YAAY,QAAQ,eAAe;AAGvD,QAAM,WAAW,YAAY,kBAAkB,CAAC;AAEhD,MAAI,CAAC;AAAU,UAAM,IAAI,MAAM,0CAA0C;AAGzE,QAAM,oBAAoB;AAAA,IACtB,WAAW,YAAY,QAAQ;AAAA,IAC/B,sBAAsB,wBAAwB,MAAM,MAAM;AAAA;AAAA,EAC9D;AAEA,QAAM,eAAe,YAAY,QAAQ,qBAAqB;AAAA,IAAI,iBAC9D,mBAAmB,YAAY,SAAS,aAAa,WAAW;AAAA,EACpE;AAEA,QAAM,aAAa,kBAAkB,aAAa,YAAY,iBAAiB;AAE/E,SAAO;AAAA,IACH,kBAAkB,EAAE,SAAS,YAAY,QAAQ,CAAC;AAAA,IAClD,QAAM,uBAAuB,SAAS,SAAS,GAA2B,EAAE;AAAA,IAC5E,QAAM,qCAAqC,mBAAmB,EAAE;AAAA,IAChE,QACI,aAAa,OAAO,CAAC,KAAK,gBAAgB;AACtC,aAAO,6BAA6B,aAAa,GAAG;AAAA,IACxD,GAAG,EAAE;AAAA,IACT,QAAO,YAAY,WAAW,SAAS,EAAE,GAAG,IAAI,WAAW,IAAI;AAAA,EACnE;AACJ","sourcesContent":["import type { Base58EncodedAddress } from '@solana/addresses';\nimport { pipe } from '@solana/functional';\nimport type { IAccountMeta, IInstruction } from '@solana/instructions';\nimport { AccountRole } from '@solana/instructions';\nimport type { Ed25519Signature } from '@solana/keys';\nimport type {\n Blockhash,\n ITransactionWithBlockhashLifetime,\n ITransactionWithFeePayer,\n ITransactionWithSignatures,\n Transaction,\n} from '@solana/transactions';\nimport {\n appendTransactionInstruction,\n createTransaction,\n setTransactionFeePayer,\n setTransactionLifetimeUsingBlockhash,\n} from '@solana/transactions';\nimport type {\n MessageAccountKeys,\n MessageCompiledInstruction,\n PublicKey,\n VersionedMessage,\n VersionedTransaction,\n} from '@solana/web3.js';\n\nfunction convertAccount(\n message: VersionedMessage,\n accountKeys: MessageAccountKeys,\n accountIndex: number\n): IAccountMeta {\n const accountPublicKey = accountKeys.get(accountIndex);\n if (!accountPublicKey) {\n // TODO coded error\n throw new Error(`Could not find account address at index ${accountIndex}`);\n }\n const isSigner = message.isAccountSigner(accountIndex);\n const isWritable = message.isAccountWritable(accountIndex);\n\n const role = isSigner\n ? isWritable\n ? AccountRole.WRITABLE_SIGNER\n : AccountRole.READONLY_SIGNER\n : isWritable\n ? AccountRole.WRITABLE\n : AccountRole.READONLY;\n\n return {\n address: accountPublicKey.toBase58() as Base58EncodedAddress,\n role,\n };\n}\n\nfunction convertInstruction(\n message: VersionedMessage,\n accountKeys: MessageAccountKeys,\n instruction: MessageCompiledInstruction\n): IInstruction {\n const programAddressPublicKey = accountKeys.get(instruction.programIdIndex);\n if (!programAddressPublicKey) {\n // TODO coded error\n throw new Error(`Could not find program address at index ${instruction.programIdIndex}`);\n }\n\n const accounts = instruction.accountKeyIndexes.map(accountIndex =>\n convertAccount(message, accountKeys, accountIndex)\n );\n\n return {\n programAddress: programAddressPublicKey.toBase58() as Base58EncodedAddress,\n ...(accounts.length ? { accounts } : {}),\n ...(instruction.data.length ? { data: instruction.data } : {}),\n };\n}\n\nfunction convertSignatures(\n transaction: VersionedTransaction,\n staticAccountKeys: PublicKey[]\n): ITransactionWithSignatures['signatures'] {\n return transaction.signatures.reduce((acc, sig, index) => {\n // legacy web3js includes a fake all 0 signature if it hasn't been signed\n // we don't do that for the new tx model. So just skip if it's all 0s\n const allZeros = sig.every(byte => byte === 0);\n if (allZeros) return acc;\n\n const address = staticAccountKeys[index].toBase58() as Base58EncodedAddress;\n return { ...acc, [address]: sig as Ed25519Signature };\n }, {});\n}\n\nexport function fromVersionedTransactionWithBlockhash(\n transaction: VersionedTransaction,\n lastValidBlockHeight?: bigint\n): Transaction & ITransactionWithFeePayer & ITransactionWithBlockhashLifetime {\n // TODO: add support for address table lookups\n // - will need to take `AddressLookupTableAccounts[]` as input\n // - will need to convert account instructions to `IAccountLookupMeta` when appropriate\n if (transaction.message.addressTableLookups.length > 0) {\n // TODO coded error\n throw new Error('Cannot convert transaction with addressTableLookups');\n }\n\n const accountKeys = transaction.message.getAccountKeys();\n\n // Fee payer is first account\n const feePayer = accountKeys.staticAccountKeys[0];\n // TODO: coded error\n if (!feePayer) throw new Error('No fee payer set in VersionedTransaction');\n\n // TOOD: add support for durable nonce transactions\n const blockhashLifetime = {\n blockhash: transaction.message.recentBlockhash as Blockhash,\n lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n, // U64 MAX\n };\n\n const instructions = transaction.message.compiledInstructions.map(instruction =>\n convertInstruction(transaction.message, accountKeys, instruction)\n );\n\n const signatures = convertSignatures(transaction, accountKeys.staticAccountKeys);\n\n return pipe(\n createTransaction({ version: transaction.version }),\n tx => setTransactionFeePayer(feePayer.toBase58() as Base58EncodedAddress, tx),\n tx => setTransactionLifetimeUsingBlockhash(blockhashLifetime, tx),\n tx =>\n instructions.reduce((acc, instruction) => {\n return appendTransactionInstruction(instruction, acc);\n }, tx),\n tx => (transaction.signatures.length ? { ...tx, signatures } : tx)\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/address.ts","../src/keypair.ts","../../codecs-core/dist/index.browser.js","../../codecs-strings/dist/index.browser.js","../../addresses/src/address.ts","../src/transaction.ts"],"names":["e"],"mappings":";AAQO,SAAS,oBAA6C,WAAyC;AAClG,SAAO,UAAU,SAAS;AAC9B;;;ACVA,SAAS,iCAAiC;AAQ1C,eAAsB,kBAAkB,SAAkB,aAA+C;AACrG,QAAM,CAAC,WAAW,UAAU,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC9C,OAAO,OAAO,UAAU,OAAO,QAAQ,UAAU,QAAQ,GAAG,WAAW,MAAM,CAAC,QAAQ,CAAC;AAAA,IACvF,0BAA0B,QAAQ,UAAU,MAAM,GAAG,EAAE,GAAG,WAAW;AAAA,EACzE,CAAC;AACD,SAAO;AAAA,IACH;AAAA,IACA;AAAA,EACJ;AACJ;;;ACwBA,SAAS,eAAe,OAAO,SAAS;AACtC,SAAO,eAAe,UAAU,QAAQ,YAAY,QAAQ,iBAAiB,KAAK;AACpF;AACA,SAAS,cAAc,SAAS;AAC9B,SAAO,OAAO,OAAO;AAAA,IACnB,GAAG;AAAA,IACH,QAAQ,CAAC,UAAU;AACjB,YAAM,QAAQ,IAAI,WAAW,eAAe,OAAO,OAAO,CAAC;AAC3D,cAAQ,MAAM,OAAO,OAAO,CAAC;AAC7B,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACH;;;ACjDA,SAAS,sBAAsB,WAAW,WAAW,aAAa,WAAW;AAC3E,MAAI,CAAC,UAAU,MAAM,IAAI,OAAO,KAAK,SAAS,KAAK,CAAC,GAAG;AACrD,UAAM,IAAI,MAAM,6BAA6B,UAAU,MAAM,UAAU,UAAU,IAAI;AAAA,EACvF;AACF;AACA,IAAI,kBAAkB,CAAC,cAAc;AACnC,SAAO,cAAc;AAAA,IACnB,kBAAkB,CAAC,UAAU;AAC3B,YAAM,CAAC,eAAe,SAAS,IAAI,uBAAuB,OAAO,UAAU,CAAC,CAAC;AAC7E,UAAI,cAAc;AAChB,eAAO,MAAM;AACf,YAAM,eAAe,mBAAmB,WAAW,SAAS;AAC5D,aAAO,cAAc,SAAS,KAAK,KAAK,aAAa,SAAS,EAAE,EAAE,SAAS,CAAC;AAAA,IAC9E;AAAA,IACA,MAAM,OAAO,OAAO,QAAQ;AAC1B,4BAAsB,WAAW,KAAK;AACtC,UAAI,UAAU;AACZ,eAAO;AACT,YAAM,CAAC,eAAe,SAAS,IAAI,uBAAuB,OAAO,UAAU,CAAC,CAAC;AAC7E,UAAI,cAAc,IAAI;AACpB,cAAM,IAAI,IAAI,WAAW,cAAc,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM;AAC9D,eAAO,SAAS,cAAc;AAAA,MAChC;AACA,UAAI,eAAe,mBAAmB,WAAW,SAAS;AAC1D,YAAM,YAAY,CAAC;AACnB,aAAO,eAAe,IAAI;AACxB,kBAAU,QAAQ,OAAO,eAAe,IAAI,CAAC;AAC7C,wBAAgB;AAAA,MAClB;AACA,YAAM,aAAa,CAAC,GAAG,MAAM,cAAc,MAAM,EAAE,KAAK,CAAC,GAAG,GAAG,SAAS;AACxE,YAAM,IAAI,YAAY,MAAM;AAC5B,aAAO,SAAS,WAAW;AAAA,IAC7B;AAAA,EACF,CAAC;AACH;AAmBA,SAAS,uBAAuB,OAAO,eAAe;AACpD,QAAM,mBAAmB,CAAC,GAAG,KAAK,EAAE,UAAU,CAAC,MAAM,MAAM,aAAa;AACxE,SAAO,qBAAqB,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,MAAM,GAAG,gBAAgB,GAAG,MAAM,MAAM,gBAAgB,CAAC;AACjH;AACA,SAAS,mBAAmB,OAAO,WAAW;AAC5C,QAAM,OAAO,OAAO,UAAU,MAAM;AACpC,SAAO,CAAC,GAAG,KAAK,EAAE,OAAO,CAAC,KAAK,SAAS,MAAM,OAAO,OAAO,UAAU,QAAQ,IAAI,CAAC,GAAG,EAAE;AAC1F;AAoCA,IAAI,YAAY;AAChB,IAAI,mBAAmB,MAAM,gBAAgB,SAAS;AAsFtD,IAAI,IAAI,WAAW;AACnB,IAAI,IAAI,WAAW;;;ACnLnB,IAAA;AAOA,SAAI,2BAAA;AAEJ,MAAA,CAAA;AACI,4BAAK,iBAAA;AAAuB,SAAA;AAC5B;AA0BJ,SAAA,gBAAA,iBAAA;AAEO,MAAA;AACH;;MAEI,gBAAA,SAAA;MAEI,gBAAgB,SAAS;MAEzB;AACF,YAAA,IAAA,MAAA,+DAAA;IACE;AACJ,UAAA,gBAAA,yBAAA;AAEA,UAAM,QAAA,cAAgB,OAAA,eAAyB;AAC/C,UAAM,WAAQ,MAAA;AACd,QAAA,aAAiB,IAAA;AACjB,YAAI,IAAA,MAAa,gFAAI,QAAA,EAAA;IACjB;EAA0G,SAC9GA,IAAA;AACJ,UAAA,IAAY,MAAA,KAAA,eAAA,uCAAA;MACR,OAAMA;IAAqE,CAAA;EAChE;AACV;;;ACpET,SAAS,YAAY;AAErB,SAAS,mBAAmB;AAE5B;AAAA,EACI;AAAA,EAEA;AAAA,EAEA;AAAA,EAKA;AAAA,EACA;AAAA,EACA;AAAA,OAEG;AASP,SAAS,eACL,SACA,aACA,cACY;AACZ,QAAM,mBAAmB,YAAY,IAAI,YAAY;AACrD,MAAI,CAAC,kBAAkB;AAEnB,UAAM,IAAI,MAAM,2CAA2C,YAAY,EAAE;AAAA,EAC7E;AACA,QAAM,WAAW,QAAQ,gBAAgB,YAAY;AACrD,QAAM,aAAa,QAAQ,kBAAkB,YAAY;AAEzD,QAAM,OAAO,WACP,aACI,YAAY,kBACZ,YAAY,kBAChB,aACE,YAAY,WACZ,YAAY;AAEpB,SAAO;AAAA,IACH,SAAS,iBAAiB,SAAS;AAAA,IACnC;AAAA,EACJ;AACJ;AAEA,SAAS,mBACL,SACA,aACA,aACY;AACZ,QAAM,0BAA0B,YAAY,IAAI,YAAY,cAAc;AAC1E,MAAI,CAAC,yBAAyB;AAE1B,UAAM,IAAI,MAAM,2CAA2C,YAAY,cAAc,EAAE;AAAA,EAC3F;AAEA,QAAM,WAAW,YAAY,kBAAkB;AAAA,IAAI,kBAC/C,eAAe,SAAS,aAAa,YAAY;AAAA,EACrD;AAEA,SAAO;AAAA,IACH,gBAAgB,wBAAwB,SAAS;AAAA,IACjD,GAAI,SAAS,SAAS,EAAE,SAAS,IAAI,CAAC;AAAA,IACtC,GAAI,YAAY,KAAK,SAAS,EAAE,MAAM,YAAY,KAAK,IAAI,CAAC;AAAA,EAChE;AACJ;AAEA,SAAS,kBACL,aACA,mBACwC;AACxC,SAAO,YAAY,WAAW,OAAO,CAAC,KAAK,KAAK,UAAU;AAGtD,UAAM,WAAW,IAAI,MAAM,UAAQ,SAAS,CAAC;AAC7C,QAAI;AAAU,aAAO;AAErB,UAAM,UAAU,kBAAkB,KAAK,EAAE,SAAS;AAClD,WAAO,EAAE,GAAG,KAAK,CAAC,OAAO,GAAG,IAAsB;AAAA,EACtD,GAAG,CAAC,CAAC;AACT;AAEO,SAAS,sCACZ,aACA,sBAC0E;AAI1E,MAAI,YAAY,QAAQ,oBAAoB,SAAS,GAAG;AAEpD,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACzE;AAEA,QAAM,cAAc,YAAY,QAAQ,eAAe;AAGvD,QAAM,WAAW,YAAY,kBAAkB,CAAC;AAEhD,MAAI,CAAC;AAAU,UAAM,IAAI,MAAM,0CAA0C;AAEzE,QAAM,oBAAoB;AAAA,IACtB,WAAW,YAAY,QAAQ;AAAA,IAC/B,sBAAsB,wBAAwB,MAAM,MAAM;AAAA;AAAA,EAC9D;AAEA,QAAM,eAAe,YAAY,QAAQ,qBAAqB;AAAA,IAAI,iBAC9D,mBAAmB,YAAY,SAAS,aAAa,WAAW;AAAA,EACpE;AAEA,QAAM,aAAa,kBAAkB,aAAa,YAAY,iBAAiB;AAE/E,SAAO;AAAA,IACH,kBAAkB,EAAE,SAAS,YAAY,QAAQ,CAAC;AAAA,IAClD,QAAM,uBAAuB,SAAS,SAAS,GAAc,EAAE;AAAA,IAC/D,QAAM,qCAAqC,mBAAmB,EAAE;AAAA,IAChE,QACI,aAAa,OAAO,CAAC,KAAK,gBAAgB;AACtC,aAAO,6BAA6B,aAAa,GAAG;AAAA,IACxD,GAAG,EAAE;AAAA,IACT,QAAO,YAAY,WAAW,SAAS,EAAE,GAAG,IAAI,WAAW,IAAI;AAAA,EACnE;AACJ;AAEO,SAAS,yCACZ,aACiE;AAIjE,MAAI,YAAY,QAAQ,oBAAoB,SAAS,GAAG;AAEpD,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACzE;AAEA,QAAM,cAAc,YAAY,QAAQ,eAAe;AAGvD,QAAM,WAAW,YAAY,kBAAkB,CAAC;AAEhD,MAAI,CAAC;AAAU,UAAM,IAAI,MAAM,0CAA0C;AAEzE,QAAM,eAAe,YAAY,QAAQ,qBAAqB;AAAA,IAAI,iBAC9D,mBAAmB,YAAY,SAAS,aAAa,WAAW;AAAA,EACpE;AAGA,MAAI,aAAa,WAAW,GAAG;AAE3B,UAAM,IAAI,MAAM,sEAAsE;AAAA,EAC1F;AAEA,MAAI,CAAC,iCAAiC,aAAa,CAAC,CAAC,GAAG;AAEpD,UAAM,IAAI,MAAM,wEAAwE;AAAA,EAC5F;AAGA,QAAM,sBAAsB,aAAa,CAAC,EAAE,SAAU,CAAC,EAAE;AACzD,kBAAgB,mBAAmB;AAEnC,QAAM,wBAAwB,aAAa,CAAC,EAAE,SAAU,CAAC,EAAE;AAC3D,kBAAgB,qBAAqB;AAErC,QAAM,uBAAuB;AAAA,IACzB,OAAO,YAAY,QAAQ;AAAA,IAC3B;AAAA,IACA;AAAA,EACJ;AAEA,QAAM,aAAa,kBAAkB,aAAa,YAAY,iBAAiB;AAE/E,SAAO;AAAA,IACH,kBAAkB,EAAE,SAAS,YAAY,QAAQ,CAAC;AAAA,IAClD,QAAM,uBAAuB,SAAS,SAAS,GAAc,EAAE;AAAA,IAC/D,QAAM,wCAAwC,sBAAsB,EAAE;AAAA,IACtE,QACI,aAAa,MAAM,CAAC,EAAE,OAAO,CAAC,KAAK,gBAAgB;AAC/C,aAAO,6BAA6B,aAAa,GAAG;AAAA,IACxD,GAAG,EAAE;AAAA,IACT,QAAO,YAAY,WAAW,SAAS,EAAE,GAAG,IAAI,WAAW,IAAI;AAAA,EACnE;AACJ","sourcesContent":["import { Address } from '@solana/addresses';\nimport { PublicKey } from '@solana/web3.js';\n\n/**\n * Convert from a Legacy Web3 JS PublicKey to a base58 encoded address\n * @param publicKey The PublicKey to convert\n * @returns An Address\n */\nexport function fromLegacyPublicKey<TAddress extends string>(publicKey: PublicKey): Address<TAddress> {\n return publicKey.toBase58() as Address<TAddress>;\n}\n","import { createPrivateKeyFromBytes } from '@solana/keys';\nimport { Keypair } from '@solana/web3.js';\n\n/**\n * Convert from a Legacy Web3 JS Keypair to a CryptoKeyPair\n * @param keypair The Keypair to convert\n * @returns A CryptoKeyPair\n */\nexport async function fromLegacyKeypair(keypair: Keypair, extractable?: boolean): Promise<CryptoKeyPair> {\n const [publicKey, privateKey] = await Promise.all([\n crypto.subtle.importKey('raw', keypair.publicKey.toBytes(), 'Ed25519', true, ['verify']),\n createPrivateKeyFromBytes(keypair.secretKey.slice(0, 32), extractable),\n ]);\n return {\n privateKey,\n publicKey,\n } as CryptoKeyPair;\n}\n","// src/assertions.ts\nfunction assertByteArrayIsNotEmptyForCodec(codecDescription, bytes, offset = 0) {\n if (bytes.length - offset <= 0) {\n throw new Error(`Codec [${codecDescription}] cannot decode empty byte arrays.`);\n }\n}\nfunction assertByteArrayHasEnoughBytesForCodec(codecDescription, expected, bytes, offset = 0) {\n const bytesLength = bytes.length - offset;\n if (bytesLength < expected) {\n throw new Error(`Codec [${codecDescription}] expected ${expected} bytes, got ${bytesLength}.`);\n }\n}\n\n// src/bytes.ts\nvar mergeBytes = (byteArrays) => {\n const nonEmptyByteArrays = byteArrays.filter((arr) => arr.length);\n if (nonEmptyByteArrays.length === 0) {\n return byteArrays.length ? byteArrays[0] : new Uint8Array();\n }\n if (nonEmptyByteArrays.length === 1) {\n return nonEmptyByteArrays[0];\n }\n const totalLength = nonEmptyByteArrays.reduce((total, arr) => total + arr.length, 0);\n const result = new Uint8Array(totalLength);\n let offset = 0;\n nonEmptyByteArrays.forEach((arr) => {\n result.set(arr, offset);\n offset += arr.length;\n });\n return result;\n};\nvar padBytes = (bytes, length) => {\n if (bytes.length >= length)\n return bytes;\n const paddedBytes = new Uint8Array(length).fill(0);\n paddedBytes.set(bytes);\n return paddedBytes;\n};\nvar fixBytes = (bytes, length) => padBytes(bytes.length <= length ? bytes : bytes.slice(0, length), length);\n\n// src/codec.ts\nfunction getEncodedSize(value, encoder) {\n return \"fixedSize\" in encoder ? encoder.fixedSize : encoder.getSizeFromValue(value);\n}\nfunction createEncoder(encoder) {\n return Object.freeze({\n ...encoder,\n encode: (value) => {\n const bytes = new Uint8Array(getEncodedSize(value, encoder));\n encoder.write(value, bytes, 0);\n return bytes;\n }\n });\n}\nfunction createDecoder(decoder) {\n return Object.freeze({\n ...decoder,\n decode: (bytes, offset = 0) => decoder.read(bytes, offset)[0]\n });\n}\nfunction createCodec(codec) {\n return Object.freeze({\n ...codec,\n decode: (bytes, offset = 0) => codec.read(bytes, offset)[0],\n encode: (value) => {\n const bytes = new Uint8Array(getEncodedSize(value, codec));\n codec.write(value, bytes, 0);\n return bytes;\n }\n });\n}\nfunction isFixedSize(codec) {\n return \"fixedSize\" in codec && typeof codec.fixedSize === \"number\";\n}\nfunction assertIsFixedSize(codec, message) {\n if (!isFixedSize(codec)) {\n throw new Error(message ?? \"Expected a fixed-size codec, got a variable-size one.\");\n }\n}\nfunction isVariableSize(codec) {\n return !isFixedSize(codec);\n}\nfunction assertIsVariableSize(codec, message) {\n if (!isVariableSize(codec)) {\n throw new Error(message ?? \"Expected a variable-size codec, got a fixed-size one.\");\n }\n}\n\n// src/combine-codec.ts\nfunction combineCodec(encoder, decoder) {\n if (isFixedSize(encoder) !== isFixedSize(decoder)) {\n throw new Error(`Encoder and decoder must either both be fixed-size or variable-size.`);\n }\n if (isFixedSize(encoder) && isFixedSize(decoder) && encoder.fixedSize !== decoder.fixedSize) {\n throw new Error(\n `Encoder and decoder must have the same fixed size, got [${encoder.fixedSize}] and [${decoder.fixedSize}].`\n );\n }\n if (!isFixedSize(encoder) && !isFixedSize(decoder) && encoder.maxSize !== decoder.maxSize) {\n throw new Error(\n `Encoder and decoder must have the same max size, got [${encoder.maxSize}] and [${decoder.maxSize}].`\n );\n }\n return {\n ...decoder,\n ...encoder,\n decode: decoder.decode,\n encode: encoder.encode,\n read: decoder.read,\n write: encoder.write\n };\n}\n\n// src/fix-codec.ts\nfunction fixEncoder(encoder, fixedBytes) {\n return createEncoder({\n fixedSize: fixedBytes,\n write: (value, bytes, offset) => {\n const variableByteArray = encoder.encode(value);\n const fixedByteArray = variableByteArray.length > fixedBytes ? variableByteArray.slice(0, fixedBytes) : variableByteArray;\n bytes.set(fixedByteArray, offset);\n return offset + fixedBytes;\n }\n });\n}\nfunction fixDecoder(decoder, fixedBytes) {\n return createDecoder({\n fixedSize: fixedBytes,\n read: (bytes, offset) => {\n assertByteArrayHasEnoughBytesForCodec(\"fixCodec\", fixedBytes, bytes, offset);\n if (offset > 0 || bytes.length > fixedBytes) {\n bytes = bytes.slice(offset, offset + fixedBytes);\n }\n if (isFixedSize(decoder)) {\n bytes = fixBytes(bytes, decoder.fixedSize);\n }\n const [value] = decoder.read(bytes, 0);\n return [value, offset + fixedBytes];\n }\n });\n}\nfunction fixCodec(codec, fixedBytes) {\n return combineCodec(fixEncoder(codec, fixedBytes), fixDecoder(codec, fixedBytes));\n}\n\n// src/map-codec.ts\nfunction mapEncoder(encoder, unmap) {\n return createEncoder({\n ...isVariableSize(encoder) ? { ...encoder, getSizeFromValue: (value) => encoder.getSizeFromValue(unmap(value)) } : encoder,\n write: (value, bytes, offset) => encoder.write(unmap(value), bytes, offset)\n });\n}\nfunction mapDecoder(decoder, map) {\n return createDecoder({\n ...decoder,\n read: (bytes, offset) => {\n const [value, newOffset] = decoder.read(bytes, offset);\n return [map(value, bytes, offset), newOffset];\n }\n });\n}\nfunction mapCodec(codec, unmap, map) {\n return createCodec({\n ...mapEncoder(codec, unmap),\n read: map ? mapDecoder(codec, map).read : codec.read\n });\n}\n\n// src/reverse-codec.ts\nfunction reverseEncoder(encoder) {\n assertIsFixedSize(encoder, \"Cannot reverse a codec of variable size.\");\n return createEncoder({\n ...encoder,\n write: (value, bytes, offset) => {\n const newOffset = encoder.write(value, bytes, offset);\n const slice = bytes.slice(offset, offset + encoder.fixedSize).reverse();\n bytes.set(slice, offset);\n return newOffset;\n }\n });\n}\nfunction reverseDecoder(decoder) {\n assertIsFixedSize(decoder, \"Cannot reverse a codec of variable size.\");\n return createDecoder({\n ...decoder,\n read: (bytes, offset) => {\n const reverseEnd = offset + decoder.fixedSize;\n if (offset === 0 && bytes.length === reverseEnd) {\n return decoder.read(bytes.reverse(), offset);\n }\n const reversedBytes = bytes.slice();\n reversedBytes.set(bytes.slice(offset, reverseEnd).reverse(), offset);\n return decoder.read(reversedBytes, offset);\n }\n });\n}\nfunction reverseCodec(codec) {\n return combineCodec(reverseEncoder(codec), reverseDecoder(codec));\n}\n\nexport { assertByteArrayHasEnoughBytesForCodec, assertByteArrayIsNotEmptyForCodec, assertIsFixedSize, assertIsVariableSize, combineCodec, createCodec, createDecoder, createEncoder, fixBytes, fixCodec, fixDecoder, fixEncoder, getEncodedSize, isFixedSize, isVariableSize, mapCodec, mapDecoder, mapEncoder, mergeBytes, padBytes, reverseCodec, reverseDecoder, reverseEncoder };\n","import { createEncoder, createDecoder, combineCodec, fixEncoder, getEncodedSize, fixDecoder, assertByteArrayIsNotEmptyForCodec, assertByteArrayHasEnoughBytesForCodec } from '@solana/codecs-core';\nimport { getU32Encoder, getU32Decoder } from '@solana/codecs-numbers';\n\n// src/assertions.ts\nfunction assertValidBaseString(alphabet4, testValue, givenValue = testValue) {\n if (!testValue.match(new RegExp(`^[${alphabet4}]*$`))) {\n throw new Error(`Expected a string of base ${alphabet4.length}, got [${givenValue}].`);\n }\n}\nvar getBaseXEncoder = (alphabet4) => {\n return createEncoder({\n getSizeFromValue: (value) => {\n const [leadingZeroes, tailChars] = partitionLeadingZeroes(value, alphabet4[0]);\n if (tailChars === \"\")\n return value.length;\n const base10Number = getBigIntFromBaseX(tailChars, alphabet4);\n return leadingZeroes.length + Math.ceil(base10Number.toString(16).length / 2);\n },\n write(value, bytes, offset) {\n assertValidBaseString(alphabet4, value);\n if (value === \"\")\n return offset;\n const [leadingZeroes, tailChars] = partitionLeadingZeroes(value, alphabet4[0]);\n if (tailChars === \"\") {\n bytes.set(new Uint8Array(leadingZeroes.length).fill(0), offset);\n return offset + leadingZeroes.length;\n }\n let base10Number = getBigIntFromBaseX(tailChars, alphabet4);\n const tailBytes = [];\n while (base10Number > 0n) {\n tailBytes.unshift(Number(base10Number % 256n));\n base10Number /= 256n;\n }\n const bytesToAdd = [...Array(leadingZeroes.length).fill(0), ...tailBytes];\n bytes.set(bytesToAdd, offset);\n return offset + bytesToAdd.length;\n }\n });\n};\nvar getBaseXDecoder = (alphabet4) => {\n return createDecoder({\n read(rawBytes, offset) {\n const bytes = offset === 0 ? rawBytes : rawBytes.slice(offset);\n if (bytes.length === 0)\n return [\"\", 0];\n let trailIndex = bytes.findIndex((n) => n !== 0);\n trailIndex = trailIndex === -1 ? bytes.length : trailIndex;\n const leadingZeroes = alphabet4[0].repeat(trailIndex);\n if (trailIndex === bytes.length)\n return [leadingZeroes, rawBytes.length];\n const base10Number = bytes.slice(trailIndex).reduce((sum, byte) => sum * 256n + BigInt(byte), 0n);\n const tailChars = getBaseXFromBigInt(base10Number, alphabet4);\n return [leadingZeroes + tailChars, rawBytes.length];\n }\n });\n};\nvar getBaseXCodec = (alphabet4) => combineCodec(getBaseXEncoder(alphabet4), getBaseXDecoder(alphabet4));\nfunction partitionLeadingZeroes(value, zeroCharacter) {\n const leadingZeroIndex = [...value].findIndex((c) => c !== zeroCharacter);\n return leadingZeroIndex === -1 ? [value, \"\"] : [value.slice(0, leadingZeroIndex), value.slice(leadingZeroIndex)];\n}\nfunction getBigIntFromBaseX(value, alphabet4) {\n const base = BigInt(alphabet4.length);\n return [...value].reduce((sum, char) => sum * base + BigInt(alphabet4.indexOf(char)), 0n);\n}\nfunction getBaseXFromBigInt(value, alphabet4) {\n const base = BigInt(alphabet4.length);\n const tailChars = [];\n while (value > 0n) {\n tailChars.unshift(alphabet4[Number(value % base)]);\n value /= base;\n }\n return tailChars.join(\"\");\n}\n\n// src/base10.ts\nvar alphabet = \"0123456789\";\nvar getBase10Encoder = () => getBaseXEncoder(alphabet);\nvar getBase10Decoder = () => getBaseXDecoder(alphabet);\nvar getBase10Codec = () => getBaseXCodec(alphabet);\nvar getBase16Encoder = () => createEncoder({\n getSizeFromValue: (value) => Math.ceil(value.length / 2),\n write(value, bytes, offset) {\n const lowercaseValue = value.toLowerCase();\n assertValidBaseString(\"0123456789abcdef\", lowercaseValue, value);\n const matches = lowercaseValue.match(/.{1,2}/g);\n const hexBytes = matches ? matches.map((byte) => parseInt(byte, 16)) : [];\n bytes.set(hexBytes, offset);\n return hexBytes.length + offset;\n }\n});\nvar getBase16Decoder = () => createDecoder({\n read(bytes, offset) {\n const value = bytes.slice(offset).reduce((str, byte) => str + byte.toString(16).padStart(2, \"0\"), \"\");\n return [value, bytes.length];\n }\n});\nvar getBase16Codec = () => combineCodec(getBase16Encoder(), getBase16Decoder());\n\n// src/base58.ts\nvar alphabet2 = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\nvar getBase58Encoder = () => getBaseXEncoder(alphabet2);\nvar getBase58Decoder = () => getBaseXDecoder(alphabet2);\nvar getBase58Codec = () => getBaseXCodec(alphabet2);\nvar getBaseXResliceEncoder = (alphabet4, bits) => createEncoder({\n getSizeFromValue: (value) => Math.floor(value.length * bits / 8),\n write(value, bytes, offset) {\n assertValidBaseString(alphabet4, value);\n if (value === \"\")\n return offset;\n const charIndices = [...value].map((c) => alphabet4.indexOf(c));\n const reslicedBytes = reslice(charIndices, bits, 8, false);\n bytes.set(reslicedBytes, offset);\n return reslicedBytes.length + offset;\n }\n});\nvar getBaseXResliceDecoder = (alphabet4, bits) => createDecoder({\n read(rawBytes, offset = 0) {\n const bytes = offset === 0 ? rawBytes : rawBytes.slice(offset);\n if (bytes.length === 0)\n return [\"\", rawBytes.length];\n const charIndices = reslice([...bytes], 8, bits, true);\n return [charIndices.map((i) => alphabet4[i]).join(\"\"), rawBytes.length];\n }\n});\nvar getBaseXResliceCodec = (alphabet4, bits) => combineCodec(getBaseXResliceEncoder(alphabet4, bits), getBaseXResliceDecoder(alphabet4, bits));\nfunction reslice(input, inputBits, outputBits, useRemainder) {\n const output = [];\n let accumulator = 0;\n let bitsInAccumulator = 0;\n const mask = (1 << outputBits) - 1;\n for (const value of input) {\n accumulator = accumulator << inputBits | value;\n bitsInAccumulator += inputBits;\n while (bitsInAccumulator >= outputBits) {\n bitsInAccumulator -= outputBits;\n output.push(accumulator >> bitsInAccumulator & mask);\n }\n }\n if (useRemainder && bitsInAccumulator > 0) {\n output.push(accumulator << outputBits - bitsInAccumulator & mask);\n }\n return output;\n}\nvar getBase64Encoder = () => {\n {\n return createEncoder({\n getSizeFromValue: (value) => {\n try {\n return atob(value).length;\n } catch (e2) {\n throw new Error(`Expected a string of base 64, got [${value}].`);\n }\n },\n write(value, bytes, offset) {\n try {\n const bytesToAdd = atob(value).split(\"\").map((c) => c.charCodeAt(0));\n bytes.set(bytesToAdd, offset);\n return bytesToAdd.length + offset;\n } catch (e2) {\n throw new Error(`Expected a string of base 64, got [${value}].`);\n }\n }\n });\n }\n};\nvar getBase64Decoder = () => {\n {\n return createDecoder({\n read(bytes, offset = 0) {\n const slice = bytes.slice(offset);\n const value = btoa(String.fromCharCode(...slice));\n return [value, bytes.length];\n }\n });\n }\n};\nvar getBase64Codec = () => combineCodec(getBase64Encoder(), getBase64Decoder());\n\n// src/null-characters.ts\nvar removeNullCharacters = (value) => (\n // eslint-disable-next-line no-control-regex\n value.replace(/\\u0000/g, \"\")\n);\nvar padNullCharacters = (value, chars) => value.padEnd(chars, \"\\0\");\n\n// ../text-encoding-impl/dist/index.browser.js\nvar e = globalThis.TextDecoder;\nvar o = globalThis.TextEncoder;\n\n// src/utf8.ts\nvar getUtf8Encoder = () => {\n let textEncoder;\n return createEncoder({\n getSizeFromValue: (value) => (textEncoder ||= new o()).encode(value).length,\n write: (value, bytes, offset) => {\n const bytesToAdd = (textEncoder ||= new o()).encode(value);\n bytes.set(bytesToAdd, offset);\n return offset + bytesToAdd.length;\n }\n });\n};\nvar getUtf8Decoder = () => {\n let textDecoder;\n return createDecoder({\n read(bytes, offset) {\n const value = (textDecoder ||= new e()).decode(bytes.slice(offset));\n return [removeNullCharacters(value), bytes.length];\n }\n });\n};\nvar getUtf8Codec = () => combineCodec(getUtf8Encoder(), getUtf8Decoder());\n\n// src/string.ts\nfunction getStringEncoder(config = {}) {\n const size = config.size ?? getU32Encoder();\n const encoding = config.encoding ?? getUtf8Encoder();\n if (size === \"variable\") {\n return encoding;\n }\n if (typeof size === \"number\") {\n return fixEncoder(encoding, size);\n }\n return createEncoder({\n getSizeFromValue: (value) => {\n const contentSize = getEncodedSize(value, encoding);\n return getEncodedSize(contentSize, size) + contentSize;\n },\n write: (value, bytes, offset) => {\n const contentSize = getEncodedSize(value, encoding);\n offset = size.write(contentSize, bytes, offset);\n return encoding.write(value, bytes, offset);\n }\n });\n}\nfunction getStringDecoder(config = {}) {\n const size = config.size ?? getU32Decoder();\n const encoding = config.encoding ?? getUtf8Decoder();\n if (size === \"variable\") {\n return encoding;\n }\n if (typeof size === \"number\") {\n return fixDecoder(encoding, size);\n }\n return createDecoder({\n read: (bytes, offset = 0) => {\n assertByteArrayIsNotEmptyForCodec(\"string\", bytes, offset);\n const [lengthBigInt, lengthOffset] = size.read(bytes, offset);\n const length = Number(lengthBigInt);\n offset = lengthOffset;\n const contentBytes = bytes.slice(offset, offset + length);\n assertByteArrayHasEnoughBytesForCodec(\"string\", length, contentBytes);\n const [value, contentOffset] = encoding.read(contentBytes, 0);\n offset += contentOffset;\n return [value, offset];\n }\n });\n}\nfunction getStringCodec(config = {}) {\n return combineCodec(getStringEncoder(config), getStringDecoder(config));\n}\n\nexport { assertValidBaseString, getBase10Codec, getBase10Decoder, getBase10Encoder, getBase16Codec, getBase16Decoder, getBase16Encoder, getBase58Codec, getBase58Decoder, getBase58Encoder, getBase64Codec, getBase64Decoder, getBase64Encoder, getBaseXCodec, getBaseXDecoder, getBaseXEncoder, getBaseXResliceCodec, getBaseXResliceDecoder, getBaseXResliceEncoder, getStringCodec, getStringDecoder, getStringEncoder, getUtf8Codec, getUtf8Decoder, getUtf8Encoder, padNullCharacters, removeNullCharacters };\n","import {\n combineCodec,\n Decoder,\n Encoder,\n FixedSizeCodec,\n FixedSizeDecoder,\n FixedSizeEncoder,\n mapEncoder,\n} from '@solana/codecs-core';\nimport { getBase58Decoder, getBase58Encoder, getStringDecoder, getStringEncoder } from '@solana/codecs-strings';\n\nexport type Address<TAddress extends string = string> = TAddress & {\n readonly __brand: unique symbol;\n};\n\nlet memoizedBase58Encoder: Encoder<string> | undefined;\nlet memoizedBase58Decoder: Decoder<string> | undefined;\n\nfunction getMemoizedBase58Encoder(): Encoder<string> {\n if (!memoizedBase58Encoder) memoizedBase58Encoder = getBase58Encoder();\n return memoizedBase58Encoder;\n}\n\nfunction getMemoizedBase58Decoder(): Decoder<string> {\n if (!memoizedBase58Decoder) memoizedBase58Decoder = getBase58Decoder();\n return memoizedBase58Decoder;\n}\n\nexport function isAddress(putativeAddress: string): putativeAddress is Address<typeof putativeAddress> {\n // Fast-path; see if the input string is of an acceptable length.\n if (\n // Lowest address (32 bytes of zeroes)\n putativeAddress.length < 32 ||\n // Highest address (32 bytes of 255)\n putativeAddress.length > 44\n ) {\n return false;\n }\n // Slow-path; actually attempt to decode the input string.\n const base58Encoder = getMemoizedBase58Encoder();\n const bytes = base58Encoder.encode(putativeAddress);\n const numBytes = bytes.byteLength;\n if (numBytes !== 32) {\n return false;\n }\n return true;\n}\n\nexport function assertIsAddress(putativeAddress: string): asserts putativeAddress is Address<typeof putativeAddress> {\n try {\n // Fast-path; see if the input string is of an acceptable length.\n if (\n // Lowest address (32 bytes of zeroes)\n putativeAddress.length < 32 ||\n // Highest address (32 bytes of 255)\n putativeAddress.length > 44\n ) {\n throw new Error('Expected input string to decode to a byte array of length 32.');\n }\n // Slow-path; actually attempt to decode the input string.\n const base58Encoder = getMemoizedBase58Encoder();\n const bytes = base58Encoder.encode(putativeAddress);\n const numBytes = bytes.byteLength;\n if (numBytes !== 32) {\n throw new Error(`Expected input string to decode to a byte array of length 32. Actual length: ${numBytes}`);\n }\n } catch (e) {\n throw new Error(`\\`${putativeAddress}\\` is not a base-58 encoded address`, {\n cause: e,\n });\n }\n}\n\nexport function address<TAddress extends string = string>(putativeAddress: TAddress): Address<TAddress> {\n assertIsAddress(putativeAddress);\n return putativeAddress as Address<TAddress>;\n}\n\nexport function getAddressEncoder(): FixedSizeEncoder<Address, 32> {\n return mapEncoder(getStringEncoder({ encoding: getMemoizedBase58Encoder(), size: 32 }), putativeAddress =>\n address(putativeAddress),\n );\n}\n\nexport function getAddressDecoder(): FixedSizeDecoder<Address, 32> {\n return getStringDecoder({ encoding: getMemoizedBase58Decoder(), size: 32 }) as FixedSizeDecoder<Address, 32>;\n}\n\nexport function getAddressCodec(): FixedSizeCodec<Address, Address, 32> {\n return combineCodec(getAddressEncoder(), getAddressDecoder());\n}\n\nexport function getAddressComparator(): (x: string, y: string) => number {\n return new Intl.Collator('en', {\n caseFirst: 'lower',\n ignorePunctuation: false,\n localeMatcher: 'best fit',\n numeric: false,\n sensitivity: 'variant',\n usage: 'sort',\n }).compare;\n}\n","import { type Address, assertIsAddress } from '@solana/addresses';\nimport { pipe } from '@solana/functional';\nimport type { IAccountMeta, IInstruction } from '@solana/instructions';\nimport { AccountRole } from '@solana/instructions';\nimport type { SignatureBytes } from '@solana/keys';\nimport {\n appendTransactionInstruction,\n type Blockhash,\n createTransaction,\n type IDurableNonceTransaction,\n isAdvanceNonceAccountInstruction,\n type ITransactionWithBlockhashLifetime,\n type ITransactionWithFeePayer,\n type ITransactionWithSignatures,\n type Nonce,\n setTransactionFeePayer,\n setTransactionLifetimeUsingBlockhash,\n setTransactionLifetimeUsingDurableNonce,\n type Transaction,\n} from '@solana/transactions';\nimport type {\n MessageAccountKeys,\n MessageCompiledInstruction,\n PublicKey,\n VersionedMessage,\n VersionedTransaction,\n} from '@solana/web3.js';\n\nfunction convertAccount(\n message: VersionedMessage,\n accountKeys: MessageAccountKeys,\n accountIndex: number,\n): IAccountMeta {\n const accountPublicKey = accountKeys.get(accountIndex);\n if (!accountPublicKey) {\n // TODO coded error\n throw new Error(`Could not find account address at index ${accountIndex}`);\n }\n const isSigner = message.isAccountSigner(accountIndex);\n const isWritable = message.isAccountWritable(accountIndex);\n\n const role = isSigner\n ? isWritable\n ? AccountRole.WRITABLE_SIGNER\n : AccountRole.READONLY_SIGNER\n : isWritable\n ? AccountRole.WRITABLE\n : AccountRole.READONLY;\n\n return {\n address: accountPublicKey.toBase58() as Address,\n role,\n };\n}\n\nfunction convertInstruction(\n message: VersionedMessage,\n accountKeys: MessageAccountKeys,\n instruction: MessageCompiledInstruction,\n): IInstruction {\n const programAddressPublicKey = accountKeys.get(instruction.programIdIndex);\n if (!programAddressPublicKey) {\n // TODO coded error\n throw new Error(`Could not find program address at index ${instruction.programIdIndex}`);\n }\n\n const accounts = instruction.accountKeyIndexes.map(accountIndex =>\n convertAccount(message, accountKeys, accountIndex),\n );\n\n return {\n programAddress: programAddressPublicKey.toBase58() as Address,\n ...(accounts.length ? { accounts } : {}),\n ...(instruction.data.length ? { data: instruction.data } : {}),\n };\n}\n\nfunction convertSignatures(\n transaction: VersionedTransaction,\n staticAccountKeys: PublicKey[],\n): ITransactionWithSignatures['signatures'] {\n return transaction.signatures.reduce((acc, sig, index) => {\n // legacy web3js includes a fake all 0 signature if it hasn't been signed\n // we don't do that for the new tx model. So just skip if it's all 0s\n const allZeros = sig.every(byte => byte === 0);\n if (allZeros) return acc;\n\n const address = staticAccountKeys[index].toBase58() as Address;\n return { ...acc, [address]: sig as SignatureBytes };\n }, {});\n}\n\nexport function fromVersionedTransactionWithBlockhash(\n transaction: VersionedTransaction,\n lastValidBlockHeight?: bigint,\n): Transaction & ITransactionWithFeePayer & ITransactionWithBlockhashLifetime {\n // TODO: add support for address table lookups\n // - will need to take `AddressLookupTableAccounts[]` as input\n // - will need to convert account instructions to `IAccountLookupMeta` when appropriate\n if (transaction.message.addressTableLookups.length > 0) {\n // TODO coded error\n throw new Error('Cannot convert transaction with addressTableLookups');\n }\n\n const accountKeys = transaction.message.getAccountKeys();\n\n // Fee payer is first account\n const feePayer = accountKeys.staticAccountKeys[0];\n // TODO: coded error\n if (!feePayer) throw new Error('No fee payer set in VersionedTransaction');\n\n const blockhashLifetime = {\n blockhash: transaction.message.recentBlockhash as Blockhash,\n lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n, // U64 MAX\n };\n\n const instructions = transaction.message.compiledInstructions.map(instruction =>\n convertInstruction(transaction.message, accountKeys, instruction),\n );\n\n const signatures = convertSignatures(transaction, accountKeys.staticAccountKeys);\n\n return pipe(\n createTransaction({ version: transaction.version }),\n tx => setTransactionFeePayer(feePayer.toBase58() as Address, tx),\n tx => setTransactionLifetimeUsingBlockhash(blockhashLifetime, tx),\n tx =>\n instructions.reduce((acc, instruction) => {\n return appendTransactionInstruction(instruction, acc);\n }, tx),\n tx => (transaction.signatures.length ? { ...tx, signatures } : tx),\n );\n}\n\nexport function fromVersionedTransactionWithDurableNonce(\n transaction: VersionedTransaction,\n): Transaction & ITransactionWithFeePayer & IDurableNonceTransaction {\n // TODO: add support for address table lookups\n // - will need to take `AddressLookupTableAccounts[]` as input\n // - will need to convert account instructions to `IAccountLookupMeta` when appropriate\n if (transaction.message.addressTableLookups.length > 0) {\n // TODO coded error\n throw new Error('Cannot convert transaction with addressTableLookups');\n }\n\n const accountKeys = transaction.message.getAccountKeys();\n\n // Fee payer is first account\n const feePayer = accountKeys.staticAccountKeys[0];\n // TODO: coded error\n if (!feePayer) throw new Error('No fee payer set in VersionedTransaction');\n\n const instructions = transaction.message.compiledInstructions.map(instruction =>\n convertInstruction(transaction.message, accountKeys, instruction),\n );\n\n // Check first instruction is durable nonce + extract params\n if (instructions.length === 0) {\n // TODO: coded error\n throw new Error('transaction with no instructions cannot be durable nonce transaction');\n }\n\n if (!isAdvanceNonceAccountInstruction(instructions[0])) {\n // TODO: coded error\n throw new Error('transaction first instruction is not advance nonce account instruction');\n }\n\n // We know these accounts are defined because we checked `isAdvanceNonceAccountInstruction`\n const nonceAccountAddress = instructions[0].accounts![0].address;\n assertIsAddress(nonceAccountAddress);\n\n const nonceAuthorityAddress = instructions[0].accounts![2].address;\n assertIsAddress(nonceAuthorityAddress);\n\n const durableNonceLifetime = {\n nonce: transaction.message.recentBlockhash as Nonce,\n nonceAccountAddress,\n nonceAuthorityAddress,\n };\n\n const signatures = convertSignatures(transaction, accountKeys.staticAccountKeys);\n\n return pipe(\n createTransaction({ version: transaction.version }),\n tx => setTransactionFeePayer(feePayer.toBase58() as Address, tx),\n tx => setTransactionLifetimeUsingDurableNonce(durableNonceLifetime, tx),\n tx =>\n instructions.slice(1).reduce((acc, instruction) => {\n return appendTransactionInstruction(instruction, acc);\n }, tx),\n tx => (transaction.signatures.length ? { ...tx, signatures } : tx),\n );\n}\n"]}