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.
- package/LICENSE +202 -0
- package/README.md +61 -0
- package/lib/cjs/deference.js +81 -0
- package/lib/cjs/errors.js +61 -0
- package/lib/cjs/errors.js.map +1 -0
- package/lib/cjs/field.js +34 -0
- package/lib/cjs/field.js.map +1 -0
- package/lib/cjs/index.js +21 -0
- package/lib/cjs/index.js.map +1 -0
- package/lib/cjs/instruction.js +95 -0
- package/lib/cjs/instruction.js.map +1 -0
- package/lib/cjs/package.json +1 -0
- package/lib/cjs/state.js +54 -0
- package/lib/cjs/state.js.map +1 -0
- package/lib/esm/errors.js +51 -0
- package/lib/esm/errors.js.map +1 -0
- package/lib/esm/field.js +29 -0
- package/lib/esm/field.js.map +1 -0
- package/lib/esm/index.js +5 -0
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/instruction.js +87 -0
- package/lib/esm/instruction.js.map +1 -0
- package/lib/esm/state.js +52 -0
- package/lib/esm/state.js.map +1 -0
- package/lib/types/errors.d.ts +29 -0
- package/lib/types/errors.d.ts.map +1 -0
- package/lib/types/field.d.ts +20 -0
- package/lib/types/field.d.ts.map +1 -0
- package/lib/types/index.d.ts +5 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/instruction.d.ts +56 -0
- package/lib/types/instruction.d.ts.map +1 -0
- package/lib/types/state.d.ts +14 -0
- package/lib/types/state.d.ts.map +1 -0
- package/package.json +79 -0
- package/src/errors.ts +39 -0
- package/src/field.ts +30 -0
- package/src/index.ts +4 -0
- package/src/instruction.ts +173 -0
- package/src/state.ts +72 -0
@@ -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
|
+
}
|