@@ -2,8 +2,8 @@ import chai, { expect } from 'chai';
2
2
import chaiAsPromised from 'chai-as-promised' ;
3
3
chai . use ( chaiAsPromised ) ;
4
4
5
- import type { Connection , Signer } from '@solana/web3.js' ;
6
- import { PublicKey } from '@solana/web3.js' ;
5
+ import type { AccountMeta , Connection , Signer } from '@solana/web3.js' ;
6
+ import { PublicKey , TransactionInstruction } from '@solana/web3.js' ;
7
7
import { sendAndConfirmTransaction , Keypair , SystemProgram , Transaction } from '@solana/web3.js' ;
8
8
import {
9
9
createInitializeMintInstruction ,
@@ -15,31 +15,56 @@ import {
15
15
updateTransferHook ,
16
16
AuthorityType ,
17
17
setAuthority ,
18
+ createAssociatedTokenAccountInstruction ,
19
+ getAssociatedTokenAddressSync ,
20
+ ASSOCIATED_TOKEN_PROGRAM_ID ,
21
+ createMintToCheckedInstruction ,
22
+ getExtraAccountMetaAccount ,
23
+ ExtraAccountMetaListLayout ,
24
+ ExtraAccountMetaLayout ,
25
+ transferCheckedWithTransferHook ,
26
+ createAssociatedTokenAccountIdempotent ,
18
27
} from '../../src' ;
19
- import { TEST_PROGRAM_ID , newAccountWithLamports , getConnection } from '../common' ;
28
+ import { TEST_PROGRAM_ID , newAccountWithLamports , getConnection , TRANSFER_HOOK_TEST_PROGRAM_ID } from '../common' ;
29
+ import { createHash } from 'crypto' ;
20
30
21
31
const TEST_TOKEN_DECIMALS = 2 ;
22
32
const EXTENSIONS = [ ExtensionType . TransferHook ] ;
23
33
describe ( 'transferHook' , ( ) => {
24
34
let connection : Connection ;
25
35
let payer : Signer ;
36
+ let payerAta : PublicKey ;
37
+ let destinationAuthority : PublicKey ;
38
+ let destinationAta : PublicKey ;
26
39
let transferHookAuthority : Keypair ;
40
+ let pdaExtraAccountMeta : PublicKey ;
27
41
let mint : PublicKey ;
28
- let transferHookProgramId : PublicKey ;
29
- let newTransferHookProgramId : PublicKey ;
30
42
before ( async ( ) => {
31
43
connection = await getConnection ( ) ;
32
44
payer = await newAccountWithLamports ( connection , 1000000000 ) ;
45
+ destinationAuthority = Keypair . generate ( ) . publicKey ;
33
46
transferHookAuthority = Keypair . generate ( ) ;
34
- transferHookProgramId = Keypair . generate ( ) . publicKey ;
35
- newTransferHookProgramId = Keypair . generate ( ) . publicKey ;
36
47
} ) ;
37
48
beforeEach ( async ( ) => {
38
49
const mintKeypair = Keypair . generate ( ) ;
39
50
mint = mintKeypair . publicKey ;
51
+ pdaExtraAccountMeta = getExtraAccountMetaAccount ( TRANSFER_HOOK_TEST_PROGRAM_ID , mint ) ;
52
+ payerAta = getAssociatedTokenAddressSync (
53
+ mint ,
54
+ payer . publicKey ,
55
+ false ,
56
+ TEST_PROGRAM_ID ,
57
+ ASSOCIATED_TOKEN_PROGRAM_ID
58
+ ) ;
59
+ destinationAta = getAssociatedTokenAddressSync (
60
+ mint ,
61
+ destinationAuthority ,
62
+ false ,
63
+ TEST_PROGRAM_ID ,
64
+ ASSOCIATED_TOKEN_PROGRAM_ID
65
+ ) ;
40
66
const mintLen = getMintLen ( EXTENSIONS ) ;
41
67
const lamports = await connection . getMinimumBalanceForRentExemption ( mintLen ) ;
42
-
43
68
const transaction = new Transaction ( ) . add (
44
69
SystemProgram . createAccount ( {
45
70
fromPubkey : payer . publicKey ,
@@ -51,7 +76,7 @@ describe('transferHook', () => {
51
76
createInitializeTransferHookInstruction (
52
77
mint ,
53
78
transferHookAuthority . publicKey ,
54
- transferHookProgramId ,
79
+ TRANSFER_HOOK_TEST_PROGRAM_ID ,
55
80
TEST_PROGRAM_ID
56
81
) ,
57
82
createInitializeMintInstruction ( mint , TEST_TOKEN_DECIMALS , payer . publicKey , null , TEST_PROGRAM_ID )
@@ -65,10 +90,11 @@ describe('transferHook', () => {
65
90
expect ( transferHook ) . to . not . be . null ;
66
91
if ( transferHook !== null ) {
67
92
expect ( transferHook . authority ) . to . eql ( transferHookAuthority . publicKey ) ;
68
- expect ( transferHook . programId ) . to . eql ( transferHookProgramId ) ;
93
+ expect ( transferHook . programId ) . to . eql ( TRANSFER_HOOK_TEST_PROGRAM_ID ) ;
69
94
}
70
95
} ) ;
71
96
it ( 'can be updated' , async ( ) => {
97
+ const newTransferHookProgramId = Keypair . generate ( ) . publicKey ;
72
98
await updateTransferHook (
73
99
connection ,
74
100
payer ,
@@ -106,4 +132,93 @@ describe('transferHook', () => {
106
132
expect ( transferHook . authority ) . to . eql ( PublicKey . default ) ;
107
133
}
108
134
} ) ;
135
+ it ( 'transferChecked' , async ( ) => {
136
+ const extraAccount = Keypair . generate ( ) . publicKey ;
137
+ const keys : AccountMeta [ ] = [
138
+ { pubkey : pdaExtraAccountMeta , isSigner : false , isWritable : true } ,
139
+ { pubkey : mint , isSigner : false , isWritable : false } ,
140
+ { pubkey : payer . publicKey , isSigner : true , isWritable : false } ,
141
+ { pubkey : SystemProgram . programId , isSigner : false , isWritable : false } ,
142
+ ] ;
143
+
144
+ const data = Buffer . alloc ( 8 + 4 + ExtraAccountMetaLayout . span ) ;
145
+ const discriminator = createHash ( 'sha256' )
146
+ . update ( 'spl-transfer-hook-interface:initialize-extra-account-metas' )
147
+ . digest ( )
148
+ . subarray ( 0 , 8 ) ;
149
+ discriminator . copy ( data ) ;
150
+ ExtraAccountMetaListLayout . encode (
151
+ {
152
+ count : 1 ,
153
+ extraAccounts : [
154
+ {
155
+ discriminator : 0 ,
156
+ addressConfig : extraAccount . toBuffer ( ) ,
157
+ isSigner : false ,
158
+ isWritable : false ,
159
+ } ,
160
+ ] ,
161
+ } ,
162
+ data ,
163
+ 8
164
+ ) ;
165
+
166
+ const initExtraAccountMetaInstruction = new TransactionInstruction ( {
167
+ keys,
168
+ data,
169
+ programId : TRANSFER_HOOK_TEST_PROGRAM_ID ,
170
+ } ) ;
171
+
172
+ const setupTransaction = new Transaction ( ) . add (
173
+ initExtraAccountMetaInstruction ,
174
+ SystemProgram . transfer ( {
175
+ fromPubkey : payer . publicKey ,
176
+ toPubkey : pdaExtraAccountMeta ,
177
+ lamports : 10000000 ,
178
+ } ) ,
179
+ createAssociatedTokenAccountInstruction (
180
+ payer . publicKey ,
181
+ payerAta ,
182
+ payer . publicKey ,
183
+ mint ,
184
+ TEST_PROGRAM_ID ,
185
+ ASSOCIATED_TOKEN_PROGRAM_ID
186
+ ) ,
187
+ createMintToCheckedInstruction (
188
+ mint ,
189
+ payerAta ,
190
+ payer . publicKey ,
191
+ 5 * 10 ** TEST_TOKEN_DECIMALS ,
192
+ TEST_TOKEN_DECIMALS ,
193
+ [ ] ,
194
+ TEST_PROGRAM_ID
195
+ )
196
+ ) ;
197
+
198
+ await sendAndConfirmTransaction ( connection , setupTransaction , [ payer ] ) ;
199
+
200
+ await createAssociatedTokenAccountIdempotent (
201
+ connection ,
202
+ payer ,
203
+ mint ,
204
+ destinationAuthority ,
205
+ undefined ,
206
+ TEST_PROGRAM_ID ,
207
+ ASSOCIATED_TOKEN_PROGRAM_ID
208
+ ) ;
209
+
210
+ await transferCheckedWithTransferHook (
211
+ connection ,
212
+ payer ,
213
+ payerAta ,
214
+ mint ,
215
+ destinationAta ,
216
+ payer ,
217
+ BigInt ( 10 ** TEST_TOKEN_DECIMALS ) ,
218
+ TEST_TOKEN_DECIMALS ,
219
+ [ ] ,
220
+ undefined ,
221
+ TEST_PROGRAM_ID
222
+ ) ;
223
+ } ) ;
109
224
} ) ;
0 commit comments