sol-spltoken 0.1.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sol-spltoken might be problematic. Click here for more details.

@@ -0,0 +1,173 @@
1
+ import type { StructToEncoderTuple } from '@solana/codecs-data-structures';
2
+ import { getBooleanEncoder, getBytesEncoder, getDataEnumCodec, getStructEncoder } from '@solana/codecs-data-structures';
3
+ import { getU64Encoder } from '@solana/codecs-numbers';
4
+ import { getStringEncoder } from '@solana/codecs-strings';
5
+ import { getOptionEncoder } from '@solana/options';
6
+ import { splDiscriminate } from '@solana/spl-type-length-value';
7
+ import type { PublicKey } from '@solana/web3.js';
8
+ import { TransactionInstruction } from '@solana/web3.js';
9
+
10
+ import type { Field } from './field.js';
11
+ import { getFieldCodec, getFieldConfig } from './field.js';
12
+
13
+ function packInstruction<T extends object>(
14
+ layout: StructToEncoderTuple<T>,
15
+ discriminator: Uint8Array,
16
+ values: T
17
+ ): Buffer {
18
+ const encoder = getStructEncoder(layout);
19
+ const data = encoder.encode(values);
20
+ return Buffer.concat([discriminator, data]);
21
+ }
22
+
23
+ /**
24
+ * Initializes a TLV entry with the basic token-metadata fields.
25
+ *
26
+ * Assumes that the provided mint is an SPL token mint, that the metadata
27
+ * account is allocated and assigned to the program, and that the metadata
28
+ * account has enough lamports to cover the rent-exempt reserve.
29
+ */
30
+ export interface InitializeInstructionArgs {
31
+ programId: PublicKey;
32
+ metadata: PublicKey;
33
+ updateAuthority: PublicKey;
34
+ mint: PublicKey;
35
+ mintAuthority: PublicKey;
36
+ name: string;
37
+ symbol: string;
38
+ uri: string;
39
+ }
40
+
41
+ export function createInitializeInstruction(args: InitializeInstructionArgs): TransactionInstruction {
42
+ const { programId, metadata, updateAuthority, mint, mintAuthority, name, symbol, uri } = args;
43
+ return new TransactionInstruction({
44
+ programId,
45
+ keys: [
46
+ { isSigner: false, isWritable: true, pubkey: metadata },
47
+ { isSigner: false, isWritable: false, pubkey: updateAuthority },
48
+ { isSigner: false, isWritable: false, pubkey: mint },
49
+ { isSigner: true, isWritable: false, pubkey: mintAuthority },
50
+ ],
51
+ data: packInstruction(
52
+ [
53
+ ['name', getStringEncoder()],
54
+ ['symbol', getStringEncoder()],
55
+ ['uri', getStringEncoder()],
56
+ ],
57
+ splDiscriminate('spl_token_metadata_interface:initialize_account'),
58
+ { name, symbol, uri }
59
+ ),
60
+ });
61
+ }
62
+
63
+ /**
64
+ * If the field does not exist on the account, it will be created.
65
+ * If the field does exist, it will be overwritten.
66
+ */
67
+ export interface UpdateFieldInstruction {
68
+ programId: PublicKey;
69
+ metadata: PublicKey;
70
+ updateAuthority: PublicKey;
71
+ field: Field | string;
72
+ value: string;
73
+ }
74
+
75
+ export function createUpdateFieldInstruction(args: UpdateFieldInstruction): TransactionInstruction {
76
+ const { programId, metadata, updateAuthority, field, value } = args;
77
+ return new TransactionInstruction({
78
+ programId,
79
+ keys: [
80
+ { isSigner: false, isWritable: true, pubkey: metadata },
81
+ { isSigner: true, isWritable: false, pubkey: updateAuthority },
82
+ ],
83
+ data: packInstruction(
84
+ [
85
+ ['field', getDataEnumCodec(getFieldCodec())],
86
+ ['value', getStringEncoder()],
87
+ ],
88
+ splDiscriminate('spl_token_metadata_interface:updating_field'),
89
+ { field: getFieldConfig(field), value }
90
+ ),
91
+ });
92
+ }
93
+
94
+ export interface RemoveKeyInstructionArgs {
95
+ programId: PublicKey;
96
+ metadata: PublicKey;
97
+ updateAuthority: PublicKey;
98
+ key: string;
99
+ idempotent: boolean;
100
+ }
101
+
102
+ export function createRemoveKeyInstruction(args: RemoveKeyInstructionArgs) {
103
+ const { programId, metadata, updateAuthority, key, idempotent } = args;
104
+ return new TransactionInstruction({
105
+ programId,
106
+ keys: [
107
+ { isSigner: false, isWritable: true, pubkey: metadata },
108
+ { isSigner: true, isWritable: false, pubkey: updateAuthority },
109
+ ],
110
+ data: packInstruction(
111
+ [
112
+ ['idempotent', getBooleanEncoder()],
113
+ ['key', getStringEncoder()],
114
+ ],
115
+ splDiscriminate('spl_token_metadata_interface:remove_key_ix'),
116
+ { idempotent, key }
117
+ ),
118
+ });
119
+ }
120
+
121
+ export interface UpdateAuthorityInstructionArgs {
122
+ programId: PublicKey;
123
+ metadata: PublicKey;
124
+ oldAuthority: PublicKey;
125
+ newAuthority: PublicKey | null;
126
+ }
127
+
128
+ export function createUpdateAuthorityInstruction(args: UpdateAuthorityInstructionArgs): TransactionInstruction {
129
+ const { programId, metadata, oldAuthority, newAuthority } = args;
130
+
131
+ const newAuthorityBuffer = Buffer.alloc(32);
132
+ if (newAuthority) {
133
+ newAuthorityBuffer.set(newAuthority.toBuffer());
134
+ } else {
135
+ newAuthorityBuffer.fill(0);
136
+ }
137
+
138
+ return new TransactionInstruction({
139
+ programId,
140
+ keys: [
141
+ { isSigner: false, isWritable: true, pubkey: metadata },
142
+ { isSigner: true, isWritable: false, pubkey: oldAuthority },
143
+ ],
144
+ data: packInstruction(
145
+ [['newAuthority', getBytesEncoder({ size: 32 })]],
146
+ splDiscriminate('spl_token_metadata_interface:update_the_authority'),
147
+ { newAuthority: newAuthorityBuffer }
148
+ ),
149
+ });
150
+ }
151
+
152
+ export interface EmitInstructionArgs {
153
+ programId: PublicKey;
154
+ metadata: PublicKey;
155
+ start?: bigint;
156
+ end?: bigint;
157
+ }
158
+
159
+ export function createEmitInstruction(args: EmitInstructionArgs): TransactionInstruction {
160
+ const { programId, metadata, start, end } = args;
161
+ return new TransactionInstruction({
162
+ programId,
163
+ keys: [{ isSigner: false, isWritable: false, pubkey: metadata }],
164
+ data: packInstruction(
165
+ [
166
+ ['start', getOptionEncoder(getU64Encoder())],
167
+ ['end', getOptionEncoder(getU64Encoder())],
168
+ ],
169
+ splDiscriminate('spl_token_metadata_interface:emitter'),
170
+ { start: start ?? null, end: end ?? null }
171
+ ),
172
+ });
173
+ }
package/src/state.ts ADDED
@@ -0,0 +1,72 @@
1
+ import { PublicKey } from '@solana/web3.js';
2
+ import { getArrayCodec, getBytesCodec, getStructCodec, getTupleCodec } from '@solana/codecs-data-structures';
3
+ import { getStringCodec } from '@solana/codecs-strings';
4
+
5
+ export const TOKEN_METADATA_DISCRIMINATOR = Buffer.from([112, 132, 90, 90, 11, 88, 157, 87]);
6
+
7
+ const tokenMetadataCodec = getStructCodec([
8
+ ['updateAuthority', getBytesCodec({ size: 32 })],
9
+ ['mint', getBytesCodec({ size: 32 })],
10
+ ['name', getStringCodec()],
11
+ ['symbol', getStringCodec()],
12
+ ['uri', getStringCodec()],
13
+ ['additionalMetadata', getArrayCodec(getTupleCodec([getStringCodec(), getStringCodec()]))],
14
+ ]);
15
+
16
+ export interface TokenMetadata {
17
+ // The authority that can sign to update the metadata
18
+ updateAuthority?: PublicKey;
19
+ // The associated mint, used to counter spoofing to be sure that metadata belongs to a particular mint
20
+ mint: PublicKey;
21
+ // The longer name of the token
22
+ name: string;
23
+ // The shortened symbol for the token
24
+ symbol: string;
25
+ // The URI pointing to richer metadata
26
+ uri: string;
27
+ // Any additional metadata about the token as key-value pairs
28
+ additionalMetadata: [string, string][];
29
+ }
30
+
31
+ // Checks if all elements in the array are 0
32
+ function isNonePubkey(buffer: Uint8Array): boolean {
33
+ for (let i = 0; i < buffer.length; i++) {
34
+ if (buffer[i] !== 0) {
35
+ return false;
36
+ }
37
+ }
38
+ return true;
39
+ }
40
+
41
+ // Pack TokenMetadata into byte slab
42
+ export const pack = (meta: TokenMetadata): Uint8Array => {
43
+ // If no updateAuthority given, set it to the None/Zero PublicKey for encoding
44
+ const updateAuthority = meta.updateAuthority ?? PublicKey.default;
45
+ return tokenMetadataCodec.encode({
46
+ ...meta,
47
+ updateAuthority: updateAuthority.toBuffer(),
48
+ mint: meta.mint.toBuffer(),
49
+ });
50
+ };
51
+
52
+ // unpack byte slab into TokenMetadata
53
+ export function unpack(buffer: Buffer | Uint8Array): TokenMetadata {
54
+ const data = tokenMetadataCodec.decode(buffer);
55
+
56
+ return isNonePubkey(data.updateAuthority)
57
+ ? {
58
+ mint: new PublicKey(data.mint),
59
+ name: data.name,
60
+ symbol: data.symbol,
61
+ uri: data.uri,
62
+ additionalMetadata: data.additionalMetadata,
63
+ }
64
+ : {
65
+ updateAuthority: new PublicKey(data.updateAuthority),
66
+ mint: new PublicKey(data.mint),
67
+ name: data.name,
68
+ symbol: data.symbol,
69
+ uri: data.uri,
70
+ additionalMetadata: data.additionalMetadata,
71
+ };
72
+ }