@solana-program/token-wrap 2.3.0 → 2.5.0
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/package.json +20 -19
- package/src/create-mint.ts +125 -0
- package/src/examples/multisig.ts +295 -0
- package/src/examples/single-signer.ts +175 -0
- package/src/examples/sync-spl-to-token2022.ts +96 -0
- package/src/examples/sync-token2022-to-spl.ts +101 -0
- package/src/generated/accounts/backpointer.ts +125 -0
- package/{dist/types/generated/accounts/index.d.ts → src/generated/accounts/index.ts} +1 -0
- package/{dist/types/generated/errors/index.d.ts → src/generated/errors/index.ts} +1 -0
- package/src/generated/errors/tokenWrap.ts +89 -0
- package/{dist/types/generated/index.d.ts → src/generated/index.ts} +1 -0
- package/src/generated/instructions/closeStuckEscrow.ts +235 -0
- package/src/generated/instructions/createMint.ts +250 -0
- package/{dist/types/generated/instructions/index.d.ts → src/generated/instructions/index.ts} +1 -0
- package/src/generated/instructions/syncMetadataToSplToken.ts +305 -0
- package/src/generated/instructions/syncMetadataToToken2022.ts +253 -0
- package/src/generated/instructions/unwrap.ts +326 -0
- package/src/generated/instructions/wrap.ts +326 -0
- package/src/generated/pdas/backpointer.ts +32 -0
- package/{dist/types/generated/pdas/index.d.ts → src/generated/pdas/index.ts} +1 -0
- package/src/generated/pdas/wrappedMint.ts +37 -0
- package/src/generated/pdas/wrappedMintAuthority.ts +32 -0
- package/{dist/types/generated/programs/index.d.ts → src/generated/programs/index.ts} +1 -0
- package/src/generated/programs/tokenWrap.ts +228 -0
- package/src/global.d.ts +8 -0
- package/src/index.ts +23 -0
- package/src/unwrap.ts +208 -0
- package/src/utilities.ts +234 -0
- package/src/wrap.ts +211 -0
- package/dist/src/index.js +0 -1292
- package/dist/src/index.js.map +0 -1
- package/dist/src/index.mjs +0 -1206
- package/dist/src/index.mjs.map +0 -1
- package/dist/types/create-mint.d.ts +0 -16
- package/dist/types/examples/multisig.d.ts +0 -1
- package/dist/types/examples/single-signer.d.ts +0 -1
- package/dist/types/examples/sync-spl-to-token2022.d.ts +0 -1
- package/dist/types/examples/sync-token2022-to-spl.d.ts +0 -1
- package/dist/types/generated/accounts/backpointer.d.ts +0 -29
- package/dist/types/generated/errors/tokenWrap.d.ts +0 -35
- package/dist/types/generated/instructions/closeStuckEscrow.d.ts +0 -63
- package/dist/types/generated/instructions/createMint.d.ts +0 -76
- package/dist/types/generated/instructions/syncMetadataToSplToken.d.ts +0 -92
- package/dist/types/generated/instructions/syncMetadataToToken2022.d.ts +0 -75
- package/dist/types/generated/instructions/unwrap.d.ts +0 -103
- package/dist/types/generated/instructions/wrap.d.ts +0 -103
- package/dist/types/generated/pdas/backpointer.d.ts +0 -14
- package/dist/types/generated/pdas/wrappedMint.d.ts +0 -15
- package/dist/types/generated/pdas/wrappedMintAuthority.d.ts +0 -14
- package/dist/types/generated/programs/tokenWrap.d.ts +0 -37
- package/dist/types/generated/shared/index.d.ts +0 -49
- package/dist/types/index.d.ts +0 -5
- package/dist/types/unwrap.d.ts +0 -45
- package/dist/types/utilities.d.ts +0 -39
- package/dist/types/wrap.d.ts +0 -42
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import {
|
|
2
|
+
address,
|
|
3
|
+
appendTransactionMessageInstructions,
|
|
4
|
+
assertIsSendableTransaction,
|
|
5
|
+
assertIsTransactionWithBlockhashLifetime,
|
|
6
|
+
createKeyPairSignerFromBytes,
|
|
7
|
+
createSolanaRpc,
|
|
8
|
+
createSolanaRpcSubscriptions,
|
|
9
|
+
createTransactionMessage,
|
|
10
|
+
getSignatureFromTransaction,
|
|
11
|
+
pipe,
|
|
12
|
+
sendAndConfirmTransactionFactory,
|
|
13
|
+
setTransactionMessageFeePayerSigner,
|
|
14
|
+
setTransactionMessageLifetimeUsingBlockhash,
|
|
15
|
+
signTransactionMessageWithSigners,
|
|
16
|
+
} from '@solana/kit';
|
|
17
|
+
import { TOKEN_2022_PROGRAM_ADDRESS } from '@solana-program/token-2022';
|
|
18
|
+
import { getAddressEncoder, getProgramDerivedAddress, getUtf8Encoder } from '@solana/kit';
|
|
19
|
+
import { findWrappedMintAuthorityPda, findWrappedMintPda, getSyncMetadataToToken2022Instruction } from '../index';
|
|
20
|
+
|
|
21
|
+
// =================================================================
|
|
22
|
+
// PREREQUISITES:
|
|
23
|
+
// =================================================================
|
|
24
|
+
// 1. An unwrapped SPL Token mint with Metaplex metadata must exist.
|
|
25
|
+
// 2. The corresponding wrapped Token-2022 mint for it must have been created
|
|
26
|
+
// via the `create-mint` command or `createMint` helper.
|
|
27
|
+
//
|
|
28
|
+
// This example ASSUMES these accounts already exist and focuses only on the
|
|
29
|
+
// transaction to sync the metadata.
|
|
30
|
+
|
|
31
|
+
// Replace these consts with the addresses from your setup
|
|
32
|
+
const PRIVATE_KEY_PAIR = new Uint8Array([
|
|
33
|
+
242, 30, 38, 177, 152, 71, 235, 193, 93, 30, 119, 131, 42, 186, 202, 7, 45, 250, 126, 135, 107, 137, 38, 91, 202,
|
|
34
|
+
212, 12, 8, 154, 213, 163, 200, 23, 237, 17, 163, 3, 135, 34, 126, 235, 146, 251, 18, 199, 101, 153, 249, 134, 88,
|
|
35
|
+
219, 68, 167, 136, 234, 195, 12, 34, 184, 85, 234, 25, 125, 94,
|
|
36
|
+
]);
|
|
37
|
+
|
|
38
|
+
// Source Mint: An existing SPL Token mint with Metaplex metadata
|
|
39
|
+
const UNWRAPPED_SPL_TOKEN_MINT = address('8owJWKMiKfMKYbPmobyZAwXibNFcY7Roj6quktaeqxGL');
|
|
40
|
+
|
|
41
|
+
async function main() {
|
|
42
|
+
const rpc = createSolanaRpc('http://127.0.0.1:8899');
|
|
43
|
+
const rpcSubscriptions = createSolanaRpcSubscriptions('ws://127.0.0.1:8900');
|
|
44
|
+
const sendAndConfirm = sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions });
|
|
45
|
+
|
|
46
|
+
const payer = await createKeyPairSignerFromBytes(PRIVATE_KEY_PAIR);
|
|
47
|
+
const { value: blockhash } = await rpc.getLatestBlockhash().send();
|
|
48
|
+
|
|
49
|
+
console.log('======== Syncing: SPL Token -> Token-2022 ========');
|
|
50
|
+
|
|
51
|
+
// To sync from an SPL Token mint, the client must resolve and provide the
|
|
52
|
+
// Metaplex Metadata PDA as the `sourceMetadata` account.
|
|
53
|
+
// Derive it using the known Metadata program and seeds: ['metadata', programId, mint]
|
|
54
|
+
const TOKEN_METADATA_PROGRAM_ADDRESS = address('metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s');
|
|
55
|
+
const [metaplexMetadataPda] = await getProgramDerivedAddress({
|
|
56
|
+
programAddress: TOKEN_METADATA_PROGRAM_ADDRESS,
|
|
57
|
+
seeds: [
|
|
58
|
+
getUtf8Encoder().encode('metadata'),
|
|
59
|
+
getAddressEncoder().encode(TOKEN_METADATA_PROGRAM_ADDRESS),
|
|
60
|
+
getAddressEncoder().encode(UNWRAPPED_SPL_TOKEN_MINT),
|
|
61
|
+
],
|
|
62
|
+
});
|
|
63
|
+
const [wrappedMint] = await findWrappedMintPda({
|
|
64
|
+
unwrappedMint: UNWRAPPED_SPL_TOKEN_MINT,
|
|
65
|
+
wrappedTokenProgram: TOKEN_2022_PROGRAM_ADDRESS,
|
|
66
|
+
});
|
|
67
|
+
const [wrappedMintAuthority] = await findWrappedMintAuthorityPda({
|
|
68
|
+
wrappedMint,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const syncToT22Ix = getSyncMetadataToToken2022Instruction({
|
|
72
|
+
wrappedMint,
|
|
73
|
+
wrappedMintAuthority,
|
|
74
|
+
unwrappedMint: UNWRAPPED_SPL_TOKEN_MINT,
|
|
75
|
+
// When the source mint is a standard SPL Token, `sourceMetadata` MUST be
|
|
76
|
+
// the address of its Metaplex Metadata PDA.
|
|
77
|
+
sourceMetadata: metaplexMetadataPda,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const transaction = await pipe(
|
|
81
|
+
createTransactionMessage({ version: 0 }),
|
|
82
|
+
tx => setTransactionMessageFeePayerSigner(payer, tx),
|
|
83
|
+
tx => setTransactionMessageLifetimeUsingBlockhash(blockhash, tx),
|
|
84
|
+
tx => appendTransactionMessageInstructions([syncToT22Ix], tx),
|
|
85
|
+
tx => signTransactionMessageWithSigners(tx),
|
|
86
|
+
);
|
|
87
|
+
assertIsSendableTransaction(transaction);
|
|
88
|
+
assertIsTransactionWithBlockhashLifetime(transaction);
|
|
89
|
+
const signature = getSignatureFromTransaction(transaction);
|
|
90
|
+
await sendAndConfirm(transaction, { commitment: 'confirmed' });
|
|
91
|
+
|
|
92
|
+
console.log('Successfully synced metadata to Token-2022 mint.');
|
|
93
|
+
console.log('Signature:', signature);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
void main();
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import {
|
|
2
|
+
address,
|
|
3
|
+
appendTransactionMessageInstructions,
|
|
4
|
+
assertIsSendableTransaction,
|
|
5
|
+
assertIsTransactionWithBlockhashLifetime,
|
|
6
|
+
createKeyPairSignerFromBytes,
|
|
7
|
+
createSolanaRpc,
|
|
8
|
+
createSolanaRpcSubscriptions,
|
|
9
|
+
createTransactionMessage,
|
|
10
|
+
getAddressEncoder,
|
|
11
|
+
getProgramDerivedAddress,
|
|
12
|
+
getSignatureFromTransaction,
|
|
13
|
+
getUtf8Encoder,
|
|
14
|
+
pipe,
|
|
15
|
+
sendAndConfirmTransactionFactory,
|
|
16
|
+
setTransactionMessageFeePayerSigner,
|
|
17
|
+
setTransactionMessageLifetimeUsingBlockhash,
|
|
18
|
+
signTransactionMessageWithSigners,
|
|
19
|
+
} from '@solana/kit';
|
|
20
|
+
import { TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';
|
|
21
|
+
import { findWrappedMintAuthorityPda, findWrappedMintPda, getSyncMetadataToSplTokenInstruction } from '../index';
|
|
22
|
+
|
|
23
|
+
// =================================================================
|
|
24
|
+
// PREREQUISITES:
|
|
25
|
+
// =================================================================
|
|
26
|
+
// 1. An unwrapped Token-2022 mint with `TokenMetadata` and `MetadataPointer`
|
|
27
|
+
// extensions must exist. The pointer should point to the mint itself.
|
|
28
|
+
// 2. The corresponding wrapped SPL Token mint for it must have been created
|
|
29
|
+
// via the `create-mint` command or `createMint` helper.
|
|
30
|
+
// 3. The wrapped mint authority PDA must be funded with enough SOL to pay for
|
|
31
|
+
// the creation of the Metaplex metadata account, as it acts as the payer
|
|
32
|
+
// for the CPI to the Metaplex program.
|
|
33
|
+
//
|
|
34
|
+
// This example ASSUMES these accounts already exist and focuses only on the
|
|
35
|
+
// transaction to sync the metadata.
|
|
36
|
+
|
|
37
|
+
// Replace these consts with the addresses from your setup
|
|
38
|
+
const PRIVATE_KEY_PAIR = new Uint8Array([
|
|
39
|
+
242, 30, 38, 177, 152, 71, 235, 193, 93, 30, 119, 131, 42, 186, 202, 7, 45, 250, 126, 135, 107, 137, 38, 91, 202,
|
|
40
|
+
212, 12, 8, 154, 213, 163, 200, 23, 237, 17, 163, 3, 135, 34, 126, 235, 146, 251, 18, 199, 101, 153, 249, 134, 88,
|
|
41
|
+
219, 68, 167, 136, 234, 195, 12, 34, 184, 85, 234, 25, 125, 94,
|
|
42
|
+
]);
|
|
43
|
+
|
|
44
|
+
// Source Mint: An existing Token-2022 mint with metadata extensions
|
|
45
|
+
const UNWRAPPED_TOKEN_2022_MINT = address('5xte8yNSUTrTtfdptekeA4QJyo8zZdanpDJojrRaXP1Y');
|
|
46
|
+
|
|
47
|
+
async function main() {
|
|
48
|
+
const rpc = createSolanaRpc('http://127.0.0.1:8899');
|
|
49
|
+
const rpcSubscriptions = createSolanaRpcSubscriptions('ws://127.0.0.1:8900');
|
|
50
|
+
const sendAndConfirm = sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions });
|
|
51
|
+
|
|
52
|
+
const payer = await createKeyPairSignerFromBytes(PRIVATE_KEY_PAIR);
|
|
53
|
+
const { value: blockhash } = await rpc.getLatestBlockhash().send();
|
|
54
|
+
|
|
55
|
+
console.log('======== Syncing: Token-2022 -> SPL Token ========');
|
|
56
|
+
|
|
57
|
+
// Derive the wrapped SPL Token mint PDA
|
|
58
|
+
const [wrappedMint] = await findWrappedMintPda({
|
|
59
|
+
unwrappedMint: UNWRAPPED_TOKEN_2022_MINT,
|
|
60
|
+
wrappedTokenProgram: TOKEN_PROGRAM_ADDRESS,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Derive the Metaplex Metadata PDA for the wrapped mint.
|
|
64
|
+
const TOKEN_METADATA_PROGRAM_ADDRESS = address('metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s');
|
|
65
|
+
const [metaplexMetadataPda] = await getProgramDerivedAddress({
|
|
66
|
+
programAddress: TOKEN_METADATA_PROGRAM_ADDRESS,
|
|
67
|
+
seeds: [
|
|
68
|
+
getUtf8Encoder().encode('metadata'),
|
|
69
|
+
getAddressEncoder().encode(TOKEN_METADATA_PROGRAM_ADDRESS),
|
|
70
|
+
getAddressEncoder().encode(wrappedMint),
|
|
71
|
+
],
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const [wrappedMintAuthority] = await findWrappedMintAuthorityPda({
|
|
75
|
+
wrappedMint,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const syncToSplIx = getSyncMetadataToSplTokenInstruction({
|
|
79
|
+
metaplexMetadata: metaplexMetadataPda,
|
|
80
|
+
wrappedMint,
|
|
81
|
+
wrappedMintAuthority,
|
|
82
|
+
unwrappedMint: UNWRAPPED_TOKEN_2022_MINT,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const transaction = await pipe(
|
|
86
|
+
createTransactionMessage({ version: 0 }),
|
|
87
|
+
tx => setTransactionMessageFeePayerSigner(payer, tx),
|
|
88
|
+
tx => setTransactionMessageLifetimeUsingBlockhash(blockhash, tx),
|
|
89
|
+
tx => appendTransactionMessageInstructions([syncToSplIx], tx),
|
|
90
|
+
tx => signTransactionMessageWithSigners(tx),
|
|
91
|
+
);
|
|
92
|
+
assertIsSendableTransaction(transaction);
|
|
93
|
+
assertIsTransactionWithBlockhashLifetime(transaction);
|
|
94
|
+
const signature = getSignatureFromTransaction(transaction);
|
|
95
|
+
await sendAndConfirm(transaction, { commitment: 'confirmed' });
|
|
96
|
+
|
|
97
|
+
console.log('Successfully synced metadata to SPL Token Metaplex account.');
|
|
98
|
+
console.log('Signature:', signature);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
void main();
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This code was AUTOGENERATED using the Codama library.
|
|
3
|
+
* Please DO NOT EDIT THIS FILE, instead use visitors
|
|
4
|
+
* to add features, then rerun Codama to update it.
|
|
5
|
+
*
|
|
6
|
+
* @see https://github.com/codama-idl/codama
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
assertAccountExists,
|
|
11
|
+
assertAccountsExist,
|
|
12
|
+
combineCodec,
|
|
13
|
+
decodeAccount,
|
|
14
|
+
fetchEncodedAccount,
|
|
15
|
+
fetchEncodedAccounts,
|
|
16
|
+
getAddressDecoder,
|
|
17
|
+
getAddressEncoder,
|
|
18
|
+
getStructDecoder,
|
|
19
|
+
getStructEncoder,
|
|
20
|
+
type Account,
|
|
21
|
+
type Address,
|
|
22
|
+
type EncodedAccount,
|
|
23
|
+
type FetchAccountConfig,
|
|
24
|
+
type FetchAccountsConfig,
|
|
25
|
+
type FixedSizeCodec,
|
|
26
|
+
type FixedSizeDecoder,
|
|
27
|
+
type FixedSizeEncoder,
|
|
28
|
+
type MaybeAccount,
|
|
29
|
+
type MaybeEncodedAccount,
|
|
30
|
+
} from '@solana/kit';
|
|
31
|
+
import { BackpointerSeeds, findBackpointerPda } from '../pdas';
|
|
32
|
+
|
|
33
|
+
/** Account to store the address of the unwrapped mint. */
|
|
34
|
+
export type Backpointer = { unwrappedMint: Address };
|
|
35
|
+
|
|
36
|
+
export type BackpointerArgs = Backpointer;
|
|
37
|
+
|
|
38
|
+
/** Gets the encoder for {@link BackpointerArgs} account data. */
|
|
39
|
+
export function getBackpointerEncoder(): FixedSizeEncoder<BackpointerArgs> {
|
|
40
|
+
return getStructEncoder([['unwrappedMint', getAddressEncoder()]]);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Gets the decoder for {@link Backpointer} account data. */
|
|
44
|
+
export function getBackpointerDecoder(): FixedSizeDecoder<Backpointer> {
|
|
45
|
+
return getStructDecoder([['unwrappedMint', getAddressDecoder()]]);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Gets the codec for {@link Backpointer} account data. */
|
|
49
|
+
export function getBackpointerCodec(): FixedSizeCodec<BackpointerArgs, Backpointer> {
|
|
50
|
+
return combineCodec(getBackpointerEncoder(), getBackpointerDecoder());
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function decodeBackpointer<TAddress extends string = string>(
|
|
54
|
+
encodedAccount: EncodedAccount<TAddress>,
|
|
55
|
+
): Account<Backpointer, TAddress>;
|
|
56
|
+
export function decodeBackpointer<TAddress extends string = string>(
|
|
57
|
+
encodedAccount: MaybeEncodedAccount<TAddress>,
|
|
58
|
+
): MaybeAccount<Backpointer, TAddress>;
|
|
59
|
+
export function decodeBackpointer<TAddress extends string = string>(
|
|
60
|
+
encodedAccount: EncodedAccount<TAddress> | MaybeEncodedAccount<TAddress>,
|
|
61
|
+
): Account<Backpointer, TAddress> | MaybeAccount<Backpointer, TAddress> {
|
|
62
|
+
return decodeAccount(encodedAccount as MaybeEncodedAccount<TAddress>, getBackpointerDecoder());
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export async function fetchBackpointer<TAddress extends string = string>(
|
|
66
|
+
rpc: Parameters<typeof fetchEncodedAccount>[0],
|
|
67
|
+
address: Address<TAddress>,
|
|
68
|
+
config?: FetchAccountConfig,
|
|
69
|
+
): Promise<Account<Backpointer, TAddress>> {
|
|
70
|
+
const maybeAccount = await fetchMaybeBackpointer(rpc, address, config);
|
|
71
|
+
assertAccountExists(maybeAccount);
|
|
72
|
+
return maybeAccount;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export async function fetchMaybeBackpointer<TAddress extends string = string>(
|
|
76
|
+
rpc: Parameters<typeof fetchEncodedAccount>[0],
|
|
77
|
+
address: Address<TAddress>,
|
|
78
|
+
config?: FetchAccountConfig,
|
|
79
|
+
): Promise<MaybeAccount<Backpointer, TAddress>> {
|
|
80
|
+
const maybeAccount = await fetchEncodedAccount(rpc, address, config);
|
|
81
|
+
return decodeBackpointer(maybeAccount);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export async function fetchAllBackpointer(
|
|
85
|
+
rpc: Parameters<typeof fetchEncodedAccounts>[0],
|
|
86
|
+
addresses: Array<Address>,
|
|
87
|
+
config?: FetchAccountsConfig,
|
|
88
|
+
): Promise<Account<Backpointer>[]> {
|
|
89
|
+
const maybeAccounts = await fetchAllMaybeBackpointer(rpc, addresses, config);
|
|
90
|
+
assertAccountsExist(maybeAccounts);
|
|
91
|
+
return maybeAccounts;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export async function fetchAllMaybeBackpointer(
|
|
95
|
+
rpc: Parameters<typeof fetchEncodedAccounts>[0],
|
|
96
|
+
addresses: Array<Address>,
|
|
97
|
+
config?: FetchAccountsConfig,
|
|
98
|
+
): Promise<MaybeAccount<Backpointer>[]> {
|
|
99
|
+
const maybeAccounts = await fetchEncodedAccounts(rpc, addresses, config);
|
|
100
|
+
return maybeAccounts.map(maybeAccount => decodeBackpointer(maybeAccount));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function getBackpointerSize(): number {
|
|
104
|
+
return 32;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export async function fetchBackpointerFromSeeds(
|
|
108
|
+
rpc: Parameters<typeof fetchEncodedAccount>[0],
|
|
109
|
+
seeds: BackpointerSeeds,
|
|
110
|
+
config: FetchAccountConfig & { programAddress?: Address } = {},
|
|
111
|
+
): Promise<Account<Backpointer>> {
|
|
112
|
+
const maybeAccount = await fetchMaybeBackpointerFromSeeds(rpc, seeds, config);
|
|
113
|
+
assertAccountExists(maybeAccount);
|
|
114
|
+
return maybeAccount;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export async function fetchMaybeBackpointerFromSeeds(
|
|
118
|
+
rpc: Parameters<typeof fetchEncodedAccount>[0],
|
|
119
|
+
seeds: BackpointerSeeds,
|
|
120
|
+
config: FetchAccountConfig & { programAddress?: Address } = {},
|
|
121
|
+
): Promise<MaybeAccount<Backpointer>> {
|
|
122
|
+
const { programAddress, ...fetchConfig } = config;
|
|
123
|
+
const [address] = await findBackpointerPda(seeds, { programAddress });
|
|
124
|
+
return await fetchMaybeBackpointer(rpc, address, fetchConfig);
|
|
125
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This code was AUTOGENERATED using the Codama library.
|
|
3
|
+
* Please DO NOT EDIT THIS FILE, instead use visitors
|
|
4
|
+
* to add features, then rerun Codama to update it.
|
|
5
|
+
*
|
|
6
|
+
* @see https://github.com/codama-idl/codama
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
isProgramError,
|
|
11
|
+
type Address,
|
|
12
|
+
type SOLANA_ERROR__INSTRUCTION_ERROR__CUSTOM,
|
|
13
|
+
type SolanaError,
|
|
14
|
+
} from '@solana/kit';
|
|
15
|
+
import { TOKEN_WRAP_PROGRAM_ADDRESS } from '../programs';
|
|
16
|
+
|
|
17
|
+
export const TOKEN_WRAP_ERROR__WRAPPED_MINT_MISMATCH = 0x0; // 0
|
|
18
|
+
export const TOKEN_WRAP_ERROR__BACKPOINTER_MISMATCH = 0x1; // 1
|
|
19
|
+
export const TOKEN_WRAP_ERROR__ZERO_WRAP_AMOUNT = 0x2; // 2
|
|
20
|
+
export const TOKEN_WRAP_ERROR__MINT_AUTHORITY_MISMATCH = 0x3; // 3
|
|
21
|
+
export const TOKEN_WRAP_ERROR__ESCROW_OWNER_MISMATCH = 0x4; // 4
|
|
22
|
+
export const TOKEN_WRAP_ERROR__INVALID_WRAPPED_MINT_OWNER = 0x5; // 5
|
|
23
|
+
export const TOKEN_WRAP_ERROR__INVALID_BACKPOINTER_OWNER = 0x6; // 6
|
|
24
|
+
export const TOKEN_WRAP_ERROR__ESCROW_MISMATCH = 0x7; // 7
|
|
25
|
+
export const TOKEN_WRAP_ERROR__ESCROW_IN_GOOD_STATE = 0x8; // 8
|
|
26
|
+
export const TOKEN_WRAP_ERROR__UNWRAPPED_MINT_HAS_NO_METADATA = 0x9; // 9
|
|
27
|
+
export const TOKEN_WRAP_ERROR__METAPLEX_METADATA_MISMATCH = 0xa; // 10
|
|
28
|
+
export const TOKEN_WRAP_ERROR__METADATA_POINTER_MISSING = 0xb; // 11
|
|
29
|
+
export const TOKEN_WRAP_ERROR__METADATA_POINTER_UNSET = 0xc; // 12
|
|
30
|
+
export const TOKEN_WRAP_ERROR__METADATA_POINTER_MISMATCH = 0xd; // 13
|
|
31
|
+
export const TOKEN_WRAP_ERROR__EXTERNAL_PROGRAM_RETURNED_NO_DATA = 0xe; // 14
|
|
32
|
+
export const TOKEN_WRAP_ERROR__NO_SYNCING_TO_TOKEN2022 = 0xf; // 15
|
|
33
|
+
|
|
34
|
+
export type TokenWrapError =
|
|
35
|
+
| typeof TOKEN_WRAP_ERROR__BACKPOINTER_MISMATCH
|
|
36
|
+
| typeof TOKEN_WRAP_ERROR__ESCROW_IN_GOOD_STATE
|
|
37
|
+
| typeof TOKEN_WRAP_ERROR__ESCROW_MISMATCH
|
|
38
|
+
| typeof TOKEN_WRAP_ERROR__ESCROW_OWNER_MISMATCH
|
|
39
|
+
| typeof TOKEN_WRAP_ERROR__EXTERNAL_PROGRAM_RETURNED_NO_DATA
|
|
40
|
+
| typeof TOKEN_WRAP_ERROR__INVALID_BACKPOINTER_OWNER
|
|
41
|
+
| typeof TOKEN_WRAP_ERROR__INVALID_WRAPPED_MINT_OWNER
|
|
42
|
+
| typeof TOKEN_WRAP_ERROR__METADATA_POINTER_MISMATCH
|
|
43
|
+
| typeof TOKEN_WRAP_ERROR__METADATA_POINTER_MISSING
|
|
44
|
+
| typeof TOKEN_WRAP_ERROR__METADATA_POINTER_UNSET
|
|
45
|
+
| typeof TOKEN_WRAP_ERROR__METAPLEX_METADATA_MISMATCH
|
|
46
|
+
| typeof TOKEN_WRAP_ERROR__MINT_AUTHORITY_MISMATCH
|
|
47
|
+
| typeof TOKEN_WRAP_ERROR__NO_SYNCING_TO_TOKEN2022
|
|
48
|
+
| typeof TOKEN_WRAP_ERROR__UNWRAPPED_MINT_HAS_NO_METADATA
|
|
49
|
+
| typeof TOKEN_WRAP_ERROR__WRAPPED_MINT_MISMATCH
|
|
50
|
+
| typeof TOKEN_WRAP_ERROR__ZERO_WRAP_AMOUNT;
|
|
51
|
+
|
|
52
|
+
let tokenWrapErrorMessages: Record<TokenWrapError, string> | undefined;
|
|
53
|
+
if (process.env['NODE_ENV'] !== 'production') {
|
|
54
|
+
tokenWrapErrorMessages = {
|
|
55
|
+
[TOKEN_WRAP_ERROR__BACKPOINTER_MISMATCH]: `Wrapped backpointer account address does not match expected PDA`,
|
|
56
|
+
[TOKEN_WRAP_ERROR__ESCROW_IN_GOOD_STATE]: `The escrow account is in a good state and cannot be recreated`,
|
|
57
|
+
[TOKEN_WRAP_ERROR__ESCROW_MISMATCH]: `Escrow account address does not match expected ATA`,
|
|
58
|
+
[TOKEN_WRAP_ERROR__ESCROW_OWNER_MISMATCH]: `Unwrapped escrow token owner is not set to expected PDA`,
|
|
59
|
+
[TOKEN_WRAP_ERROR__EXTERNAL_PROGRAM_RETURNED_NO_DATA]: `External metadata program returned no data`,
|
|
60
|
+
[TOKEN_WRAP_ERROR__INVALID_BACKPOINTER_OWNER]: `Wrapped backpointer account owner is not the expected token wrap program`,
|
|
61
|
+
[TOKEN_WRAP_ERROR__INVALID_WRAPPED_MINT_OWNER]: `Wrapped mint account owner is not the expected token program`,
|
|
62
|
+
[TOKEN_WRAP_ERROR__METADATA_POINTER_MISMATCH]: `Provided source metadata account does not match pointer`,
|
|
63
|
+
[TOKEN_WRAP_ERROR__METADATA_POINTER_MISSING]: `Metadata pointer extension missing on mint`,
|
|
64
|
+
[TOKEN_WRAP_ERROR__METADATA_POINTER_UNSET]: `Metadata pointer is unset (None)`,
|
|
65
|
+
[TOKEN_WRAP_ERROR__METAPLEX_METADATA_MISMATCH]: `Metaplex metadata account address does not match expected PDA`,
|
|
66
|
+
[TOKEN_WRAP_ERROR__MINT_AUTHORITY_MISMATCH]: `Wrapped mint authority does not match expected PDA`,
|
|
67
|
+
[TOKEN_WRAP_ERROR__NO_SYNCING_TO_TOKEN2022]: `Instruction can only be used with spl-token wrapped mints`,
|
|
68
|
+
[TOKEN_WRAP_ERROR__UNWRAPPED_MINT_HAS_NO_METADATA]: `Unwrapped mint does not have the TokenMetadata extension`,
|
|
69
|
+
[TOKEN_WRAP_ERROR__WRAPPED_MINT_MISMATCH]: `Wrapped mint account address does not match expected PDA`,
|
|
70
|
+
[TOKEN_WRAP_ERROR__ZERO_WRAP_AMOUNT]: `Wrap amount should be positive`,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function getTokenWrapErrorMessage(code: TokenWrapError): string {
|
|
75
|
+
if (process.env['NODE_ENV'] !== 'production') {
|
|
76
|
+
return (tokenWrapErrorMessages as Record<TokenWrapError, string>)[code];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return 'Error message not available in production bundles.';
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function isTokenWrapError<TProgramErrorCode extends TokenWrapError>(
|
|
83
|
+
error: unknown,
|
|
84
|
+
transactionMessage: { instructions: Record<number, { programAddress: Address }> },
|
|
85
|
+
code?: TProgramErrorCode,
|
|
86
|
+
): error is SolanaError<typeof SOLANA_ERROR__INSTRUCTION_ERROR__CUSTOM> &
|
|
87
|
+
Readonly<{ context: Readonly<{ code: TProgramErrorCode }> }> {
|
|
88
|
+
return isProgramError<TProgramErrorCode>(error, transactionMessage, TOKEN_WRAP_PROGRAM_ADDRESS, code);
|
|
89
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This code was AUTOGENERATED using the Codama library.
|
|
3
|
+
* Please DO NOT EDIT THIS FILE, instead use visitors
|
|
4
|
+
* to add features, then rerun Codama to update it.
|
|
5
|
+
*
|
|
6
|
+
* @see https://github.com/codama-idl/codama
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
combineCodec,
|
|
11
|
+
getStructDecoder,
|
|
12
|
+
getStructEncoder,
|
|
13
|
+
getU8Decoder,
|
|
14
|
+
getU8Encoder,
|
|
15
|
+
SOLANA_ERROR__PROGRAM_CLIENTS__INSUFFICIENT_ACCOUNT_METAS,
|
|
16
|
+
SolanaError,
|
|
17
|
+
transformEncoder,
|
|
18
|
+
type AccountMeta,
|
|
19
|
+
type Address,
|
|
20
|
+
type FixedSizeCodec,
|
|
21
|
+
type FixedSizeDecoder,
|
|
22
|
+
type FixedSizeEncoder,
|
|
23
|
+
type Instruction,
|
|
24
|
+
type InstructionWithAccounts,
|
|
25
|
+
type InstructionWithData,
|
|
26
|
+
type ReadonlyAccount,
|
|
27
|
+
type ReadonlyUint8Array,
|
|
28
|
+
type WritableAccount,
|
|
29
|
+
} from '@solana/kit';
|
|
30
|
+
import { getAccountMetaFactory, type ResolvedInstructionAccount } from '@solana/program-client-core';
|
|
31
|
+
import { TOKEN_WRAP_PROGRAM_ADDRESS } from '../programs';
|
|
32
|
+
|
|
33
|
+
export const CLOSE_STUCK_ESCROW_DISCRIMINATOR = 3;
|
|
34
|
+
|
|
35
|
+
export function getCloseStuckEscrowDiscriminatorBytes(): ReadonlyUint8Array {
|
|
36
|
+
return getU8Encoder().encode(CLOSE_STUCK_ESCROW_DISCRIMINATOR);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type CloseStuckEscrowInstruction<
|
|
40
|
+
TProgram extends string = typeof TOKEN_WRAP_PROGRAM_ADDRESS,
|
|
41
|
+
TAccountEscrow extends string | AccountMeta<string> = string,
|
|
42
|
+
TAccountDestination extends string | AccountMeta<string> = string,
|
|
43
|
+
TAccountUnwrappedMint extends string | AccountMeta<string> = string,
|
|
44
|
+
TAccountWrappedMint extends string | AccountMeta<string> = string,
|
|
45
|
+
TAccountWrappedMintAuthority extends string | AccountMeta<string> = string,
|
|
46
|
+
TAccountToken2022Program extends string | AccountMeta<string> = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb',
|
|
47
|
+
TRemainingAccounts extends readonly AccountMeta<string>[] = [],
|
|
48
|
+
> = Instruction<TProgram> &
|
|
49
|
+
InstructionWithData<ReadonlyUint8Array> &
|
|
50
|
+
InstructionWithAccounts<
|
|
51
|
+
[
|
|
52
|
+
TAccountEscrow extends string ? WritableAccount<TAccountEscrow> : TAccountEscrow,
|
|
53
|
+
TAccountDestination extends string ? WritableAccount<TAccountDestination> : TAccountDestination,
|
|
54
|
+
TAccountUnwrappedMint extends string ? ReadonlyAccount<TAccountUnwrappedMint> : TAccountUnwrappedMint,
|
|
55
|
+
TAccountWrappedMint extends string ? ReadonlyAccount<TAccountWrappedMint> : TAccountWrappedMint,
|
|
56
|
+
TAccountWrappedMintAuthority extends string
|
|
57
|
+
? ReadonlyAccount<TAccountWrappedMintAuthority>
|
|
58
|
+
: TAccountWrappedMintAuthority,
|
|
59
|
+
TAccountToken2022Program extends string
|
|
60
|
+
? ReadonlyAccount<TAccountToken2022Program>
|
|
61
|
+
: TAccountToken2022Program,
|
|
62
|
+
...TRemainingAccounts,
|
|
63
|
+
]
|
|
64
|
+
>;
|
|
65
|
+
|
|
66
|
+
export type CloseStuckEscrowInstructionData = { discriminator: number };
|
|
67
|
+
|
|
68
|
+
export type CloseStuckEscrowInstructionDataArgs = {};
|
|
69
|
+
|
|
70
|
+
export function getCloseStuckEscrowInstructionDataEncoder(): FixedSizeEncoder<CloseStuckEscrowInstructionDataArgs> {
|
|
71
|
+
return transformEncoder(getStructEncoder([['discriminator', getU8Encoder()]]), value => ({
|
|
72
|
+
...value,
|
|
73
|
+
discriminator: CLOSE_STUCK_ESCROW_DISCRIMINATOR,
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function getCloseStuckEscrowInstructionDataDecoder(): FixedSizeDecoder<CloseStuckEscrowInstructionData> {
|
|
78
|
+
return getStructDecoder([['discriminator', getU8Decoder()]]);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function getCloseStuckEscrowInstructionDataCodec(): FixedSizeCodec<
|
|
82
|
+
CloseStuckEscrowInstructionDataArgs,
|
|
83
|
+
CloseStuckEscrowInstructionData
|
|
84
|
+
> {
|
|
85
|
+
return combineCodec(getCloseStuckEscrowInstructionDataEncoder(), getCloseStuckEscrowInstructionDataDecoder());
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export type CloseStuckEscrowInput<
|
|
89
|
+
TAccountEscrow extends string = string,
|
|
90
|
+
TAccountDestination extends string = string,
|
|
91
|
+
TAccountUnwrappedMint extends string = string,
|
|
92
|
+
TAccountWrappedMint extends string = string,
|
|
93
|
+
TAccountWrappedMintAuthority extends string = string,
|
|
94
|
+
TAccountToken2022Program extends string = string,
|
|
95
|
+
> = {
|
|
96
|
+
/** Escrow account to close (ATA) */
|
|
97
|
+
escrow: Address<TAccountEscrow>;
|
|
98
|
+
/** Destination for lamports from closed account */
|
|
99
|
+
destination: Address<TAccountDestination>;
|
|
100
|
+
/** Unwrapped mint */
|
|
101
|
+
unwrappedMint: Address<TAccountUnwrappedMint>;
|
|
102
|
+
/** Wrapped mint */
|
|
103
|
+
wrappedMint: Address<TAccountWrappedMint>;
|
|
104
|
+
/** Wrapped mint authority (PDA) */
|
|
105
|
+
wrappedMintAuthority: Address<TAccountWrappedMintAuthority>;
|
|
106
|
+
/** Token-2022 program */
|
|
107
|
+
token2022Program?: Address<TAccountToken2022Program>;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export function getCloseStuckEscrowInstruction<
|
|
111
|
+
TAccountEscrow extends string,
|
|
112
|
+
TAccountDestination extends string,
|
|
113
|
+
TAccountUnwrappedMint extends string,
|
|
114
|
+
TAccountWrappedMint extends string,
|
|
115
|
+
TAccountWrappedMintAuthority extends string,
|
|
116
|
+
TAccountToken2022Program extends string,
|
|
117
|
+
TProgramAddress extends Address = typeof TOKEN_WRAP_PROGRAM_ADDRESS,
|
|
118
|
+
>(
|
|
119
|
+
input: CloseStuckEscrowInput<
|
|
120
|
+
TAccountEscrow,
|
|
121
|
+
TAccountDestination,
|
|
122
|
+
TAccountUnwrappedMint,
|
|
123
|
+
TAccountWrappedMint,
|
|
124
|
+
TAccountWrappedMintAuthority,
|
|
125
|
+
TAccountToken2022Program
|
|
126
|
+
>,
|
|
127
|
+
config?: { programAddress?: TProgramAddress },
|
|
128
|
+
): CloseStuckEscrowInstruction<
|
|
129
|
+
TProgramAddress,
|
|
130
|
+
TAccountEscrow,
|
|
131
|
+
TAccountDestination,
|
|
132
|
+
TAccountUnwrappedMint,
|
|
133
|
+
TAccountWrappedMint,
|
|
134
|
+
TAccountWrappedMintAuthority,
|
|
135
|
+
TAccountToken2022Program
|
|
136
|
+
> {
|
|
137
|
+
// Program address.
|
|
138
|
+
const programAddress = config?.programAddress ?? TOKEN_WRAP_PROGRAM_ADDRESS;
|
|
139
|
+
|
|
140
|
+
// Original accounts.
|
|
141
|
+
const originalAccounts = {
|
|
142
|
+
escrow: { value: input.escrow ?? null, isWritable: true },
|
|
143
|
+
destination: { value: input.destination ?? null, isWritable: true },
|
|
144
|
+
unwrappedMint: { value: input.unwrappedMint ?? null, isWritable: false },
|
|
145
|
+
wrappedMint: { value: input.wrappedMint ?? null, isWritable: false },
|
|
146
|
+
wrappedMintAuthority: { value: input.wrappedMintAuthority ?? null, isWritable: false },
|
|
147
|
+
token2022Program: { value: input.token2022Program ?? null, isWritable: false },
|
|
148
|
+
};
|
|
149
|
+
const accounts = originalAccounts as Record<keyof typeof originalAccounts, ResolvedInstructionAccount>;
|
|
150
|
+
|
|
151
|
+
// Resolve default values.
|
|
152
|
+
if (!accounts.token2022Program.value) {
|
|
153
|
+
accounts.token2022Program.value =
|
|
154
|
+
'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb' as Address<'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'>;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const getAccountMeta = getAccountMetaFactory(programAddress, 'programId');
|
|
158
|
+
return Object.freeze({
|
|
159
|
+
accounts: [
|
|
160
|
+
getAccountMeta('escrow', accounts.escrow),
|
|
161
|
+
getAccountMeta('destination', accounts.destination),
|
|
162
|
+
getAccountMeta('unwrappedMint', accounts.unwrappedMint),
|
|
163
|
+
getAccountMeta('wrappedMint', accounts.wrappedMint),
|
|
164
|
+
getAccountMeta('wrappedMintAuthority', accounts.wrappedMintAuthority),
|
|
165
|
+
getAccountMeta('token2022Program', accounts.token2022Program),
|
|
166
|
+
],
|
|
167
|
+
data: getCloseStuckEscrowInstructionDataEncoder().encode({}),
|
|
168
|
+
programAddress,
|
|
169
|
+
} as CloseStuckEscrowInstruction<
|
|
170
|
+
TProgramAddress,
|
|
171
|
+
TAccountEscrow,
|
|
172
|
+
TAccountDestination,
|
|
173
|
+
TAccountUnwrappedMint,
|
|
174
|
+
TAccountWrappedMint,
|
|
175
|
+
TAccountWrappedMintAuthority,
|
|
176
|
+
TAccountToken2022Program
|
|
177
|
+
>);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export type ParsedCloseStuckEscrowInstruction<
|
|
181
|
+
TProgram extends string = typeof TOKEN_WRAP_PROGRAM_ADDRESS,
|
|
182
|
+
TAccountMetas extends readonly AccountMeta[] = readonly AccountMeta[],
|
|
183
|
+
> = {
|
|
184
|
+
programAddress: Address<TProgram>;
|
|
185
|
+
accounts: {
|
|
186
|
+
/** Escrow account to close (ATA) */
|
|
187
|
+
escrow: TAccountMetas[0];
|
|
188
|
+
/** Destination for lamports from closed account */
|
|
189
|
+
destination: TAccountMetas[1];
|
|
190
|
+
/** Unwrapped mint */
|
|
191
|
+
unwrappedMint: TAccountMetas[2];
|
|
192
|
+
/** Wrapped mint */
|
|
193
|
+
wrappedMint: TAccountMetas[3];
|
|
194
|
+
/** Wrapped mint authority (PDA) */
|
|
195
|
+
wrappedMintAuthority: TAccountMetas[4];
|
|
196
|
+
/** Token-2022 program */
|
|
197
|
+
token2022Program?: TAccountMetas[5] | undefined;
|
|
198
|
+
};
|
|
199
|
+
data: CloseStuckEscrowInstructionData;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
export function parseCloseStuckEscrowInstruction<TProgram extends string, TAccountMetas extends readonly AccountMeta[]>(
|
|
203
|
+
instruction: Instruction<TProgram> &
|
|
204
|
+
InstructionWithAccounts<TAccountMetas> &
|
|
205
|
+
InstructionWithData<ReadonlyUint8Array>,
|
|
206
|
+
): ParsedCloseStuckEscrowInstruction<TProgram, TAccountMetas> {
|
|
207
|
+
if (instruction.accounts.length < 6) {
|
|
208
|
+
throw new SolanaError(SOLANA_ERROR__PROGRAM_CLIENTS__INSUFFICIENT_ACCOUNT_METAS, {
|
|
209
|
+
actualAccountMetas: instruction.accounts.length,
|
|
210
|
+
expectedAccountMetas: 6,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
let accountIndex = 0;
|
|
214
|
+
const getNextAccount = () => {
|
|
215
|
+
const accountMeta = (instruction.accounts as TAccountMetas)[accountIndex]!;
|
|
216
|
+
accountIndex += 1;
|
|
217
|
+
return accountMeta;
|
|
218
|
+
};
|
|
219
|
+
const getNextOptionalAccount = () => {
|
|
220
|
+
const accountMeta = getNextAccount();
|
|
221
|
+
return accountMeta.address === TOKEN_WRAP_PROGRAM_ADDRESS ? undefined : accountMeta;
|
|
222
|
+
};
|
|
223
|
+
return {
|
|
224
|
+
programAddress: instruction.programAddress,
|
|
225
|
+
accounts: {
|
|
226
|
+
escrow: getNextAccount(),
|
|
227
|
+
destination: getNextAccount(),
|
|
228
|
+
unwrappedMint: getNextAccount(),
|
|
229
|
+
wrappedMint: getNextAccount(),
|
|
230
|
+
wrappedMintAuthority: getNextAccount(),
|
|
231
|
+
token2022Program: getNextOptionalAccount(),
|
|
232
|
+
},
|
|
233
|
+
data: getCloseStuckEscrowInstructionDataDecoder().decode(instruction.data),
|
|
234
|
+
};
|
|
235
|
+
}
|