misc.ts 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608
  1. import * as anchor from "@project-serum/anchor";
  2. import { Program, BN, IdlAccounts, AnchorError } from "@project-serum/anchor";
  3. import {
  4. PublicKey,
  5. Keypair,
  6. SystemProgram,
  7. SYSVAR_RENT_PUBKEY,
  8. } from "@solana/web3.js";
  9. import {
  10. TOKEN_PROGRAM_ID,
  11. Token,
  12. ASSOCIATED_TOKEN_PROGRAM_ID,
  13. } from "@solana/spl-token";
  14. import { Misc } from "../target/types/misc";
  15. import { Misc2 } from "../target/types/misc2";
  16. const utf8 = anchor.utils.bytes.utf8;
  17. const { assert } = require("chai");
  18. const nativeAssert = require("assert");
  19. const miscIdl = require("../target/idl/misc.json");
  20. describe("misc", () => {
  21. // Configure the client to use the local cluster.
  22. anchor.setProvider(anchor.AnchorProvider.env());
  23. const program = anchor.workspace.Misc as Program<Misc>;
  24. const misc2Program = anchor.workspace.Misc2 as Program<Misc2>;
  25. it("Can allocate extra space for a state constructor", async () => {
  26. const tx = await program.state.rpc.new();
  27. const addr = await program.state.address();
  28. const state = await program.state.fetch();
  29. const accountInfo = await program.provider.connection.getAccountInfo(addr);
  30. assert.isTrue(state.v.equals(Buffer.from([])));
  31. assert.lengthOf(accountInfo.data, 99);
  32. });
  33. it("Can use remaining accounts for a state instruction", async () => {
  34. await program.state.rpc.remainingAccounts({
  35. remainingAccounts: [
  36. { pubkey: misc2Program.programId, isWritable: false, isSigner: false },
  37. ],
  38. });
  39. });
  40. const data = anchor.web3.Keypair.generate();
  41. it("Can use u128 and i128", async () => {
  42. const tx = await program.rpc.initialize(
  43. new anchor.BN(1234),
  44. new anchor.BN(22),
  45. {
  46. accounts: {
  47. data: data.publicKey,
  48. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  49. },
  50. signers: [data],
  51. instructions: [await program.account.data.createInstruction(data)],
  52. }
  53. );
  54. const dataAccount = await program.account.data.fetch(data.publicKey);
  55. assert.isTrue(dataAccount.udata.eq(new anchor.BN(1234)));
  56. assert.isTrue(dataAccount.idata.eq(new anchor.BN(22)));
  57. });
  58. it("Can use u16", async () => {
  59. const data = anchor.web3.Keypair.generate();
  60. const tx = await program.rpc.testU16(99, {
  61. accounts: {
  62. myAccount: data.publicKey,
  63. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  64. },
  65. signers: [data],
  66. instructions: [await program.account.dataU16.createInstruction(data)],
  67. });
  68. const dataAccount = await program.account.dataU16.fetch(data.publicKey);
  69. assert.strictEqual(dataAccount.data, 99);
  70. });
  71. it("Can embed programs into genesis from the Anchor.toml", async () => {
  72. const pid = new anchor.web3.PublicKey(
  73. "FtMNMKp9DZHKWUyVAsj3Q5QV8ow4P3fUPP7ZrWEQJzKr"
  74. );
  75. let accInfo = await anchor.getProvider().connection.getAccountInfo(pid);
  76. assert.isTrue(accInfo.executable);
  77. });
  78. it("Can use the owner constraint", async () => {
  79. await program.rpc.testOwner({
  80. accounts: {
  81. data: data.publicKey,
  82. misc: program.programId,
  83. },
  84. });
  85. await nativeAssert.rejects(
  86. async () => {
  87. await program.rpc.testOwner({
  88. accounts: {
  89. data: program.provider.wallet.publicKey,
  90. misc: program.programId,
  91. },
  92. });
  93. },
  94. (err) => {
  95. return true;
  96. }
  97. );
  98. });
  99. it("Can use the executable attribute", async () => {
  100. await program.rpc.testExecutable({
  101. accounts: {
  102. program: program.programId,
  103. },
  104. });
  105. await nativeAssert.rejects(
  106. async () => {
  107. await program.rpc.testExecutable({
  108. accounts: {
  109. program: program.provider.wallet.publicKey,
  110. },
  111. });
  112. },
  113. (err) => {
  114. return true;
  115. }
  116. );
  117. });
  118. it("Can CPI to state instructions", async () => {
  119. const oldData = new anchor.BN(0);
  120. await misc2Program.state.rpc.new({
  121. accounts: {
  122. authority: program.provider.wallet.publicKey,
  123. },
  124. });
  125. let stateAccount = await misc2Program.state.fetch();
  126. assert.isTrue(stateAccount.data.eq(oldData));
  127. assert.isTrue(stateAccount.auth.equals(program.provider.wallet.publicKey));
  128. const newData = new anchor.BN(2134);
  129. await program.rpc.testStateCpi(newData, {
  130. accounts: {
  131. authority: program.provider.wallet.publicKey,
  132. cpiState: await misc2Program.state.address(),
  133. misc2Program: misc2Program.programId,
  134. },
  135. });
  136. stateAccount = await misc2Program.state.fetch();
  137. assert.isTrue(stateAccount.data.eq(newData));
  138. assert.isTrue(stateAccount.auth.equals(program.provider.wallet.publicKey));
  139. });
  140. it("Can retrieve events when simulating a transaction", async () => {
  141. const resp = await program.simulate.testSimulate(44);
  142. const expectedRaw = [
  143. "Program 3TEqcc8xhrhdspwbvoamUJe2borm4Nr72JxL66k6rgrh invoke [1]",
  144. "Program log: Instruction: TestSimulate",
  145. "Program data: NgyCA9omwbMsAAAA",
  146. "Program data: fPhuIELK/k7SBAAA",
  147. "Program data: jvbowsvlmkcJAAAA",
  148. "Program data: zxM5neEnS1kBAgMEBQYHCAkK",
  149. "Program data: g06Ei2GL1gIBAgMEBQYHCAkKCw==",
  150. "Program 3TEqcc8xhrhdspwbvoamUJe2borm4Nr72JxL66k6rgrh consumed 5395 of 1400000 compute units",
  151. "Program 3TEqcc8xhrhdspwbvoamUJe2borm4Nr72JxL66k6rgrh success",
  152. ];
  153. assert.deepStrictEqual(expectedRaw, resp.raw);
  154. assert.strictEqual(resp.events[0].name, "E1");
  155. assert.strictEqual(resp.events[0].data.data, 44);
  156. assert.strictEqual(resp.events[1].name, "E2");
  157. assert.strictEqual(resp.events[1].data.data, 1234);
  158. assert.strictEqual(resp.events[2].name, "E3");
  159. assert.strictEqual(resp.events[2].data.data, 9);
  160. assert.strictEqual(resp.events[3].name, "E5");
  161. assert.deepStrictEqual(
  162. resp.events[3].data.data,
  163. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  164. );
  165. assert.strictEqual(resp.events[4].name, "E6");
  166. assert.deepStrictEqual(
  167. resp.events[4].data.data,
  168. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
  169. );
  170. });
  171. let dataI8;
  172. it("Can use i8 in the idl", async () => {
  173. dataI8 = anchor.web3.Keypair.generate();
  174. await program.rpc.testI8(-3, {
  175. accounts: {
  176. data: dataI8.publicKey,
  177. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  178. },
  179. instructions: [await program.account.dataI8.createInstruction(dataI8)],
  180. signers: [dataI8],
  181. });
  182. const dataAccount = await program.account.dataI8.fetch(dataI8.publicKey);
  183. assert.strictEqual(dataAccount.data, -3);
  184. });
  185. let dataPubkey;
  186. it("Can use i16 in the idl", async () => {
  187. const data = anchor.web3.Keypair.generate();
  188. await program.rpc.testI16(-2048, {
  189. accounts: {
  190. data: data.publicKey,
  191. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  192. },
  193. instructions: [await program.account.dataI16.createInstruction(data)],
  194. signers: [data],
  195. });
  196. const dataAccount = await program.account.dataI16.fetch(data.publicKey);
  197. assert.strictEqual(dataAccount.data, -2048);
  198. dataPubkey = data.publicKey;
  199. });
  200. it("Can use base58 strings to fetch an account", async () => {
  201. const dataAccount = await program.account.dataI16.fetch(
  202. dataPubkey.toString()
  203. );
  204. assert.strictEqual(dataAccount.data, -2048);
  205. });
  206. it("Should fail to close an account when sending lamports to itself", async () => {
  207. try {
  208. await program.rpc.testClose({
  209. accounts: {
  210. data: data.publicKey,
  211. solDest: data.publicKey,
  212. },
  213. });
  214. assert.ok(false);
  215. } catch (err) {
  216. const errMsg = "A close constraint was violated";
  217. assert.strictEqual(err.error.errorMessage, errMsg);
  218. assert.strictEqual(err.error.errorCode.number, 2011);
  219. }
  220. });
  221. it("Can close an account", async () => {
  222. const openAccount = await program.provider.connection.getAccountInfo(
  223. data.publicKey
  224. );
  225. assert.isNotNull(openAccount);
  226. let beforeBalance = (
  227. await program.provider.connection.getAccountInfo(
  228. program.provider.wallet.publicKey
  229. )
  230. ).lamports;
  231. await program.rpc.testClose({
  232. accounts: {
  233. data: data.publicKey,
  234. solDest: program.provider.wallet.publicKey,
  235. },
  236. });
  237. let afterBalance = (
  238. await program.provider.connection.getAccountInfo(
  239. program.provider.wallet.publicKey
  240. )
  241. ).lamports;
  242. // Retrieved rent exemption sol.
  243. assert.ok(afterBalance > beforeBalance);
  244. const closedAccount = await program.provider.connection.getAccountInfo(
  245. data.publicKey
  246. );
  247. assert.isNull(closedAccount);
  248. });
  249. it("Can use instruction data in accounts constraints", async () => {
  250. // b"my-seed"
  251. const seed = Buffer.from([109, 121, 45, 115, 101, 101, 100]);
  252. const [myPda, nonce] = await PublicKey.findProgramAddress(
  253. [seed, anchor.web3.SYSVAR_RENT_PUBKEY.toBuffer()],
  254. program.programId
  255. );
  256. await program.rpc.testInstructionConstraint(nonce, {
  257. accounts: {
  258. myPda,
  259. myAccount: anchor.web3.SYSVAR_RENT_PUBKEY,
  260. },
  261. });
  262. });
  263. it("Can create a PDA account with instruction data", async () => {
  264. const seed = Buffer.from([1, 2, 3, 4]);
  265. const domain = "my-domain";
  266. const foo = anchor.web3.SYSVAR_RENT_PUBKEY;
  267. const [myPda, nonce] = await PublicKey.findProgramAddress(
  268. [
  269. Buffer.from(anchor.utils.bytes.utf8.encode("my-seed")),
  270. Buffer.from(anchor.utils.bytes.utf8.encode(domain)),
  271. foo.toBuffer(),
  272. seed,
  273. ],
  274. program.programId
  275. );
  276. await program.rpc.testPdaInit(domain, seed, nonce, {
  277. accounts: {
  278. myPda,
  279. myPayer: program.provider.wallet.publicKey,
  280. foo,
  281. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  282. systemProgram: anchor.web3.SystemProgram.programId,
  283. },
  284. });
  285. const myPdaAccount = await program.account.dataU16.fetch(myPda);
  286. assert.strictEqual(myPdaAccount.data, 6);
  287. });
  288. it("Can create a zero copy PDA account", async () => {
  289. const [myPda, nonce] = await PublicKey.findProgramAddress(
  290. [Buffer.from(anchor.utils.bytes.utf8.encode("my-seed"))],
  291. program.programId
  292. );
  293. await program.rpc.testPdaInitZeroCopy({
  294. accounts: {
  295. myPda,
  296. myPayer: program.provider.wallet.publicKey,
  297. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  298. systemProgram: anchor.web3.SystemProgram.programId,
  299. },
  300. });
  301. const myPdaAccount = await program.account.dataZeroCopy.fetch(myPda);
  302. assert.strictEqual(myPdaAccount.data, 9);
  303. assert.strictEqual(myPdaAccount.bump, nonce);
  304. });
  305. it("Can write to a zero copy PDA account", async () => {
  306. const [myPda, bump] = await PublicKey.findProgramAddress(
  307. [Buffer.from(anchor.utils.bytes.utf8.encode("my-seed"))],
  308. program.programId
  309. );
  310. await program.rpc.testPdaMutZeroCopy({
  311. accounts: {
  312. myPda,
  313. myPayer: program.provider.wallet.publicKey,
  314. },
  315. });
  316. const myPdaAccount = await program.account.dataZeroCopy.fetch(myPda);
  317. assert.strictEqual(myPdaAccount.data, 1234);
  318. assert.strictEqual(myPdaAccount.bump, bump);
  319. });
  320. it("Can create a token account from seeds pda", async () => {
  321. const [mint, mint_bump] = await PublicKey.findProgramAddress(
  322. [Buffer.from(anchor.utils.bytes.utf8.encode("my-mint-seed"))],
  323. program.programId
  324. );
  325. const [myPda, token_bump] = await PublicKey.findProgramAddress(
  326. [Buffer.from(anchor.utils.bytes.utf8.encode("my-token-seed"))],
  327. program.programId
  328. );
  329. await program.rpc.testTokenSeedsInit({
  330. accounts: {
  331. myPda,
  332. mint,
  333. authority: program.provider.wallet.publicKey,
  334. systemProgram: anchor.web3.SystemProgram.programId,
  335. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  336. tokenProgram: TOKEN_PROGRAM_ID,
  337. },
  338. });
  339. const mintAccount = new Token(
  340. program.provider.connection,
  341. mint,
  342. TOKEN_PROGRAM_ID,
  343. program.provider.wallet.payer
  344. );
  345. const account = await mintAccount.getAccountInfo(myPda);
  346. assert.strictEqual(account.state, 1);
  347. assert.strictEqual(account.amount.toNumber(), 0);
  348. assert.isTrue(account.isInitialized);
  349. assert.isTrue(account.owner.equals(program.provider.wallet.publicKey));
  350. assert.isTrue(account.mint.equals(mint));
  351. });
  352. it("Can execute a fallback function", async () => {
  353. await nativeAssert.rejects(
  354. async () => {
  355. await anchor.utils.rpc.invoke(program.programId);
  356. },
  357. (err) => {
  358. assert.isTrue(err.toString().includes("custom program error: 0x4d2"));
  359. return true;
  360. }
  361. );
  362. });
  363. it("Can init a random account", async () => {
  364. const data = anchor.web3.Keypair.generate();
  365. await program.rpc.testInit({
  366. accounts: {
  367. data: data.publicKey,
  368. payer: program.provider.wallet.publicKey,
  369. systemProgram: anchor.web3.SystemProgram.programId,
  370. },
  371. signers: [data],
  372. });
  373. const account = await program.account.dataI8.fetch(data.publicKey);
  374. assert.strictEqual(account.data, 3);
  375. });
  376. it("Can init a random account prefunded", async () => {
  377. const data = anchor.web3.Keypair.generate();
  378. await program.rpc.testInit({
  379. accounts: {
  380. data: data.publicKey,
  381. payer: program.provider.wallet.publicKey,
  382. systemProgram: anchor.web3.SystemProgram.programId,
  383. },
  384. signers: [data],
  385. instructions: [
  386. anchor.web3.SystemProgram.transfer({
  387. fromPubkey: program.provider.wallet.publicKey,
  388. toPubkey: data.publicKey,
  389. lamports: 4039280,
  390. }),
  391. ],
  392. });
  393. const account = await program.account.dataI8.fetch(data.publicKey);
  394. assert.strictEqual(account.data, 3);
  395. });
  396. it("Can init a random zero copy account", async () => {
  397. const data = anchor.web3.Keypair.generate();
  398. await program.rpc.testInitZeroCopy({
  399. accounts: {
  400. data: data.publicKey,
  401. payer: program.provider.wallet.publicKey,
  402. systemProgram: anchor.web3.SystemProgram.programId,
  403. },
  404. signers: [data],
  405. });
  406. const account = await program.account.dataZeroCopy.fetch(data.publicKey);
  407. assert.strictEqual(account.data, 10);
  408. assert.strictEqual(account.bump, 2);
  409. });
  410. let mint = undefined;
  411. it("Can create a random mint account", async () => {
  412. mint = anchor.web3.Keypair.generate();
  413. await program.rpc.testInitMint({
  414. accounts: {
  415. mint: mint.publicKey,
  416. payer: program.provider.wallet.publicKey,
  417. systemProgram: anchor.web3.SystemProgram.programId,
  418. tokenProgram: TOKEN_PROGRAM_ID,
  419. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  420. },
  421. signers: [mint],
  422. });
  423. const client = new Token(
  424. program.provider.connection,
  425. mint.publicKey,
  426. TOKEN_PROGRAM_ID,
  427. program.provider.wallet.payer
  428. );
  429. const mintAccount = await client.getMintInfo();
  430. assert.strictEqual(mintAccount.decimals, 6);
  431. assert.isTrue(
  432. mintAccount.mintAuthority.equals(program.provider.wallet.publicKey)
  433. );
  434. assert.isTrue(
  435. mintAccount.freezeAuthority.equals(program.provider.wallet.publicKey)
  436. );
  437. });
  438. it("Can create a random mint account prefunded", async () => {
  439. mint = anchor.web3.Keypair.generate();
  440. await program.rpc.testInitMint({
  441. accounts: {
  442. mint: mint.publicKey,
  443. payer: program.provider.wallet.publicKey,
  444. systemProgram: anchor.web3.SystemProgram.programId,
  445. tokenProgram: TOKEN_PROGRAM_ID,
  446. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  447. },
  448. signers: [mint],
  449. instructions: [
  450. anchor.web3.SystemProgram.transfer({
  451. fromPubkey: program.provider.wallet.publicKey,
  452. toPubkey: mint.publicKey,
  453. lamports: 4039280,
  454. }),
  455. ],
  456. });
  457. const client = new Token(
  458. program.provider.connection,
  459. mint.publicKey,
  460. TOKEN_PROGRAM_ID,
  461. program.provider.wallet.payer
  462. );
  463. const mintAccount = await client.getMintInfo();
  464. assert.strictEqual(mintAccount.decimals, 6);
  465. assert.isTrue(
  466. mintAccount.mintAuthority.equals(program.provider.wallet.publicKey)
  467. );
  468. });
  469. it("Can create a random token account", async () => {
  470. const token = anchor.web3.Keypair.generate();
  471. await program.rpc.testInitToken({
  472. accounts: {
  473. token: token.publicKey,
  474. mint: mint.publicKey,
  475. payer: program.provider.wallet.publicKey,
  476. systemProgram: anchor.web3.SystemProgram.programId,
  477. tokenProgram: TOKEN_PROGRAM_ID,
  478. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  479. },
  480. signers: [token],
  481. });
  482. const client = new Token(
  483. program.provider.connection,
  484. mint.publicKey,
  485. TOKEN_PROGRAM_ID,
  486. program.provider.wallet.payer
  487. );
  488. const account = await client.getAccountInfo(token.publicKey);
  489. assert.strictEqual(account.state, 1);
  490. assert.strictEqual(account.amount.toNumber(), 0);
  491. assert.isTrue(account.isInitialized);
  492. assert.isTrue(account.owner.equals(program.provider.wallet.publicKey));
  493. assert.isTrue(account.mint.equals(mint.publicKey));
  494. });
  495. it("Can create a random token with prefunding", async () => {
  496. const token = anchor.web3.Keypair.generate();
  497. await program.rpc.testInitToken({
  498. accounts: {
  499. token: token.publicKey,
  500. mint: mint.publicKey,
  501. payer: program.provider.wallet.publicKey,
  502. systemProgram: anchor.web3.SystemProgram.programId,
  503. tokenProgram: TOKEN_PROGRAM_ID,
  504. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  505. },
  506. signers: [token],
  507. instructions: [
  508. anchor.web3.SystemProgram.transfer({
  509. fromPubkey: program.provider.wallet.publicKey,
  510. toPubkey: token.publicKey,
  511. lamports: 4039280,
  512. }),
  513. ],
  514. });
  515. const client = new Token(
  516. program.provider.connection,
  517. mint.publicKey,
  518. TOKEN_PROGRAM_ID,
  519. program.provider.wallet.payer
  520. );
  521. const account = await client.getAccountInfo(token.publicKey);
  522. assert.strictEqual(account.state, 1);
  523. assert.strictEqual(account.amount.toNumber(), 0);
  524. assert.isTrue(account.isInitialized);
  525. assert.isTrue(account.owner.equals(program.provider.wallet.publicKey));
  526. assert.isTrue(account.mint.equals(mint.publicKey));
  527. });
  528. it("Can create a random token with prefunding under the rent exemption", async () => {
  529. const token = anchor.web3.Keypair.generate();
  530. await program.rpc.testInitToken({
  531. accounts: {
  532. token: token.publicKey,
  533. mint: mint.publicKey,
  534. payer: program.provider.wallet.publicKey,
  535. systemProgram: anchor.web3.SystemProgram.programId,
  536. tokenProgram: TOKEN_PROGRAM_ID,
  537. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  538. },
  539. signers: [token],
  540. instructions: [
  541. anchor.web3.SystemProgram.transfer({
  542. fromPubkey: program.provider.wallet.publicKey,
  543. toPubkey: token.publicKey,
  544. lamports: 1,
  545. }),
  546. ],
  547. });
  548. const client = new Token(
  549. program.provider.connection,
  550. mint.publicKey,
  551. TOKEN_PROGRAM_ID,
  552. program.provider.wallet.payer
  553. );
  554. const account = await client.getAccountInfo(token.publicKey);
  555. assert.strictEqual(account.state, 1);
  556. assert.strictEqual(account.amount.toNumber(), 0);
  557. assert.isTrue(account.isInitialized);
  558. assert.isTrue(account.owner.equals(program.provider.wallet.publicKey));
  559. assert.isTrue(account.mint.equals(mint.publicKey));
  560. });
  561. it("Can initialize multiple accounts via a composite payer", async () => {
  562. const data1 = anchor.web3.Keypair.generate();
  563. const data2 = anchor.web3.Keypair.generate();
  564. const tx = await program.rpc.testCompositePayer({
  565. accounts: {
  566. composite: {
  567. data: data1.publicKey,
  568. payer: program.provider.wallet.publicKey,
  569. systemProgram: anchor.web3.SystemProgram.programId,
  570. },
  571. data: data2.publicKey,
  572. systemProgram: anchor.web3.SystemProgram.programId,
  573. },
  574. signers: [data1, data2],
  575. });
  576. const account1 = await program.account.dataI8.fetch(data1.publicKey);
  577. assert.strictEqual(account1.data, 1);
  578. const account2 = await program.account.data.fetch(data2.publicKey);
  579. assert.strictEqual(account2.udata.toNumber(), 2);
  580. assert.strictEqual(account2.idata.toNumber(), 3);
  581. });
  582. describe("associated_token constraints", () => {
  583. let associatedToken = null;
  584. // apparently cannot await here so doing it in the 'it' statements
  585. let client = Token.createMint(
  586. program.provider.connection,
  587. program.provider.wallet.payer,
  588. program.provider.wallet.publicKey,
  589. program.provider.wallet.publicKey,
  590. 9,
  591. TOKEN_PROGRAM_ID
  592. );
  593. it("Can create an associated token account", async () => {
  594. const localClient = await client;
  595. associatedToken = await Token.getAssociatedTokenAddress(
  596. ASSOCIATED_TOKEN_PROGRAM_ID,
  597. TOKEN_PROGRAM_ID,
  598. localClient.publicKey,
  599. program.provider.wallet.publicKey
  600. );
  601. await program.rpc.testInitAssociatedToken({
  602. accounts: {
  603. token: associatedToken,
  604. mint: localClient.publicKey,
  605. payer: program.provider.wallet.publicKey,
  606. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  607. systemProgram: anchor.web3.SystemProgram.programId,
  608. tokenProgram: TOKEN_PROGRAM_ID,
  609. associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
  610. },
  611. });
  612. const account = await localClient.getAccountInfo(associatedToken);
  613. assert.strictEqual(account.state, 1);
  614. assert.strictEqual(account.amount.toNumber(), 0);
  615. assert.isTrue(account.isInitialized);
  616. assert.isTrue(account.owner.equals(program.provider.wallet.publicKey));
  617. assert.isTrue(account.mint.equals(localClient.publicKey));
  618. });
  619. it("Can validate associated_token constraints", async () => {
  620. const localClient = await client;
  621. await program.rpc.testValidateAssociatedToken({
  622. accounts: {
  623. token: associatedToken,
  624. mint: localClient.publicKey,
  625. wallet: program.provider.wallet.publicKey,
  626. },
  627. });
  628. let otherMint = await Token.createMint(
  629. program.provider.connection,
  630. program.provider.wallet.payer,
  631. program.provider.wallet.publicKey,
  632. program.provider.wallet.publicKey,
  633. 9,
  634. TOKEN_PROGRAM_ID
  635. );
  636. await nativeAssert.rejects(
  637. async () => {
  638. await program.rpc.testValidateAssociatedToken({
  639. accounts: {
  640. token: associatedToken,
  641. mint: otherMint.publicKey,
  642. wallet: program.provider.wallet.publicKey,
  643. },
  644. });
  645. },
  646. (err) => {
  647. assert.strictEqual(err.error.errorCode.number, 2009);
  648. return true;
  649. }
  650. );
  651. });
  652. it("associated_token constraints check do not allow authority change", async () => {
  653. const localClient = await client;
  654. await program.rpc.testValidateAssociatedToken({
  655. accounts: {
  656. token: associatedToken,
  657. mint: localClient.publicKey,
  658. wallet: program.provider.wallet.publicKey,
  659. },
  660. });
  661. await localClient.setAuthority(
  662. associatedToken,
  663. anchor.web3.Keypair.generate().publicKey,
  664. "AccountOwner",
  665. program.provider.wallet.payer,
  666. []
  667. );
  668. await nativeAssert.rejects(
  669. async () => {
  670. await program.rpc.testValidateAssociatedToken({
  671. accounts: {
  672. token: associatedToken,
  673. mint: localClient.publicKey,
  674. wallet: program.provider.wallet.publicKey,
  675. },
  676. });
  677. },
  678. (err) => {
  679. assert.strictEqual(err.error.errorCode.number, 2015);
  680. return true;
  681. }
  682. );
  683. });
  684. });
  685. it("Can fetch all accounts of a given type", async () => {
  686. // Initialize the accounts.
  687. const data1 = anchor.web3.Keypair.generate();
  688. const data2 = anchor.web3.Keypair.generate();
  689. const data3 = anchor.web3.Keypair.generate();
  690. const data4 = anchor.web3.Keypair.generate();
  691. // Initialize filterable data.
  692. const filterable1 = anchor.web3.Keypair.generate().publicKey;
  693. const filterable2 = anchor.web3.Keypair.generate().publicKey;
  694. // Set up a secondary wallet and program.
  695. const anotherProgram = new anchor.Program(
  696. miscIdl,
  697. program.programId,
  698. new anchor.AnchorProvider(
  699. program.provider.connection,
  700. new anchor.Wallet(anchor.web3.Keypair.generate()),
  701. { commitment: program.provider.connection.commitment }
  702. )
  703. );
  704. // Request airdrop for secondary wallet.
  705. const signature = await program.provider.connection.requestAirdrop(
  706. anotherProgram.provider.wallet.publicKey,
  707. anchor.web3.LAMPORTS_PER_SOL
  708. );
  709. await program.provider.connection.confirmTransaction(signature);
  710. // Create all the accounts.
  711. await Promise.all([
  712. program.rpc.testFetchAll(filterable1, {
  713. accounts: {
  714. data: data1.publicKey,
  715. authority: program.provider.wallet.publicKey,
  716. systemProgram: anchor.web3.SystemProgram.programId,
  717. },
  718. signers: [data1],
  719. }),
  720. program.rpc.testFetchAll(filterable1, {
  721. accounts: {
  722. data: data2.publicKey,
  723. authority: program.provider.wallet.publicKey,
  724. systemProgram: anchor.web3.SystemProgram.programId,
  725. },
  726. signers: [data2],
  727. }),
  728. program.rpc.testFetchAll(filterable2, {
  729. accounts: {
  730. data: data3.publicKey,
  731. authority: program.provider.wallet.publicKey,
  732. systemProgram: anchor.web3.SystemProgram.programId,
  733. },
  734. signers: [data3],
  735. }),
  736. anotherProgram.rpc.testFetchAll(filterable1, {
  737. accounts: {
  738. data: data4.publicKey,
  739. authority: anotherProgram.provider.wallet.publicKey,
  740. systemProgram: anchor.web3.SystemProgram.programId,
  741. },
  742. signers: [data4],
  743. }),
  744. ]);
  745. // Call for multiple kinds of .all.
  746. const allAccounts = await program.account.dataWithFilter.all();
  747. const allAccountsFilteredByBuffer =
  748. await program.account.dataWithFilter.all(
  749. program.provider.wallet.publicKey.toBuffer()
  750. );
  751. const allAccountsFilteredByProgramFilters1 =
  752. await program.account.dataWithFilter.all([
  753. {
  754. memcmp: {
  755. offset: 8,
  756. bytes: program.provider.wallet.publicKey.toBase58(),
  757. },
  758. },
  759. { memcmp: { offset: 40, bytes: filterable1.toBase58() } },
  760. ]);
  761. const allAccountsFilteredByProgramFilters2 =
  762. await program.account.dataWithFilter.all([
  763. {
  764. memcmp: {
  765. offset: 8,
  766. bytes: program.provider.wallet.publicKey.toBase58(),
  767. },
  768. },
  769. { memcmp: { offset: 40, bytes: filterable2.toBase58() } },
  770. ]);
  771. // Without filters there should be 4 accounts.
  772. assert.lengthOf(allAccounts, 4);
  773. // Filtering by main wallet there should be 3 accounts.
  774. assert.lengthOf(allAccountsFilteredByBuffer, 3);
  775. // Filtering all the main wallet accounts and matching the filterable1 value
  776. // results in a 2 accounts.
  777. assert.lengthOf(allAccountsFilteredByProgramFilters1, 2);
  778. // Filtering all the main wallet accounts and matching the filterable2 value
  779. // results in 1 account.
  780. assert.lengthOf(allAccountsFilteredByProgramFilters2, 1);
  781. });
  782. it("Can use pdas with empty seeds", async () => {
  783. const [pda, bump] = await PublicKey.findProgramAddress(
  784. [],
  785. program.programId
  786. );
  787. await program.rpc.testInitWithEmptySeeds({
  788. accounts: {
  789. pda: pda,
  790. authority: program.provider.wallet.publicKey,
  791. systemProgram: anchor.web3.SystemProgram.programId,
  792. },
  793. });
  794. await program.rpc.testEmptySeedsConstraint({
  795. accounts: {
  796. pda: pda,
  797. },
  798. });
  799. const [pda2, bump2] = await PublicKey.findProgramAddress(
  800. ["non-empty"],
  801. program.programId
  802. );
  803. await nativeAssert.rejects(
  804. program.rpc.testEmptySeedsConstraint({
  805. accounts: {
  806. pda: pda2,
  807. },
  808. }),
  809. (err) => {
  810. assert.equal(err.error.errorCode.number, 2006);
  811. return true;
  812. }
  813. );
  814. });
  815. const ifNeededAcc = anchor.web3.Keypair.generate();
  816. it("Can init if needed a new account", async () => {
  817. await program.rpc.testInitIfNeeded(1, {
  818. accounts: {
  819. data: ifNeededAcc.publicKey,
  820. systemProgram: anchor.web3.SystemProgram.programId,
  821. payer: program.provider.wallet.publicKey,
  822. },
  823. signers: [ifNeededAcc],
  824. });
  825. const account = await program.account.dataU16.fetch(ifNeededAcc.publicKey);
  826. assert.strictEqual(account.data, 1);
  827. });
  828. it("Can init if needed a previously created account", async () => {
  829. await program.rpc.testInitIfNeeded(3, {
  830. accounts: {
  831. data: ifNeededAcc.publicKey,
  832. systemProgram: anchor.web3.SystemProgram.programId,
  833. payer: program.provider.wallet.publicKey,
  834. },
  835. signers: [ifNeededAcc],
  836. });
  837. const account = await program.account.dataU16.fetch(ifNeededAcc.publicKey);
  838. assert.strictEqual(account.data, 3);
  839. });
  840. it("Can use const for array size", async () => {
  841. const data = anchor.web3.Keypair.generate();
  842. const tx = await program.rpc.testConstArraySize(99, {
  843. accounts: {
  844. data: data.publicKey,
  845. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  846. },
  847. signers: [data],
  848. instructions: [
  849. await program.account.dataConstArraySize.createInstruction(data),
  850. ],
  851. });
  852. const dataAccount = await program.account.dataConstArraySize.fetch(
  853. data.publicKey
  854. );
  855. assert.deepStrictEqual(dataAccount.data, [99, ...new Array(9).fill(0)]);
  856. });
  857. it("Can use const for instruction data size", async () => {
  858. const data = anchor.web3.Keypair.generate();
  859. const dataArray = [99, ...new Array(9).fill(0)];
  860. const tx = await program.rpc.testConstIxDataSize(dataArray, {
  861. accounts: {
  862. data: data.publicKey,
  863. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  864. },
  865. signers: [data],
  866. instructions: [
  867. await program.account.dataConstArraySize.createInstruction(data),
  868. ],
  869. });
  870. const dataAccount = await program.account.dataConstArraySize.fetch(
  871. data.publicKey
  872. );
  873. assert.deepStrictEqual(dataAccount.data, dataArray);
  874. });
  875. it("Should include BASE const in IDL", async () => {
  876. assert.isDefined(
  877. miscIdl.constants.find(
  878. (c) => c.name === "BASE" && c.type === "u128" && c.value === "1_000_000"
  879. )
  880. );
  881. });
  882. it("Should include DECIMALS const in IDL", async () => {
  883. assert.isDefined(
  884. miscIdl.constants.find(
  885. (c) => c.name === "DECIMALS" && c.type === "u8" && c.value === "6"
  886. )
  887. );
  888. });
  889. it("Should not include NO_IDL const in IDL", async () => {
  890. assert.isUndefined(miscIdl.constants.find((c) => c.name === "NO_IDL"));
  891. });
  892. it("init_if_needed throws if account exists but is not owned by the expected program", async () => {
  893. const newAcc = await anchor.web3.PublicKey.findProgramAddress(
  894. [utf8.encode("hello")],
  895. program.programId
  896. );
  897. await program.rpc.testInitIfNeededChecksOwner({
  898. accounts: {
  899. data: newAcc[0],
  900. systemProgram: anchor.web3.SystemProgram.programId,
  901. payer: program.provider.wallet.publicKey,
  902. owner: program.programId,
  903. },
  904. });
  905. try {
  906. await program.rpc.testInitIfNeededChecksOwner({
  907. accounts: {
  908. data: newAcc[0],
  909. systemProgram: anchor.web3.SystemProgram.programId,
  910. payer: program.provider.wallet.publicKey,
  911. owner: anchor.web3.Keypair.generate().publicKey,
  912. },
  913. });
  914. assert.ok(false);
  915. } catch (_err) {
  916. assert.isTrue(_err instanceof AnchorError);
  917. const err: AnchorError = _err;
  918. assert.strictEqual(err.error.errorCode.number, 2004);
  919. }
  920. });
  921. it("init_if_needed throws if pda account exists but does not have the expected seeds", async () => {
  922. const newAcc = await anchor.web3.PublicKey.findProgramAddress(
  923. [utf8.encode("nothello")],
  924. program.programId
  925. );
  926. await program.rpc.testInitIfNeededChecksSeeds("nothello", {
  927. accounts: {
  928. data: newAcc[0],
  929. systemProgram: anchor.web3.SystemProgram.programId,
  930. payer: program.provider.wallet.publicKey,
  931. },
  932. });
  933. // this will throw if it is not a proper PDA
  934. // we need this so we know that the following tx failed
  935. // not because it couldn't create this pda
  936. // but because the two pdas were different
  937. anchor.web3.PublicKey.createProgramAddress(
  938. [utf8.encode("hello")],
  939. program.programId
  940. );
  941. try {
  942. await program.rpc.testInitIfNeededChecksSeeds("hello", {
  943. accounts: {
  944. data: newAcc[0],
  945. systemProgram: anchor.web3.SystemProgram.programId,
  946. payer: program.provider.wallet.publicKey,
  947. owner: anchor.web3.Keypair.generate().publicKey,
  948. },
  949. });
  950. assert.ok(false);
  951. } catch (_err) {
  952. assert.isTrue(_err instanceof AnchorError);
  953. const err: AnchorError = _err;
  954. assert.strictEqual(err.error.errorCode.number, 2006);
  955. }
  956. });
  957. it("init_if_needed throws if account exists but is not the expected space", async () => {
  958. const newAcc = anchor.web3.Keypair.generate();
  959. const _irrelevantForTest = 3;
  960. await program.rpc.initWithSpace(_irrelevantForTest, {
  961. accounts: {
  962. data: newAcc.publicKey,
  963. systemProgram: anchor.web3.SystemProgram.programId,
  964. payer: program.provider.wallet.publicKey,
  965. },
  966. signers: [newAcc],
  967. });
  968. try {
  969. await program.rpc.testInitIfNeeded(_irrelevantForTest, {
  970. accounts: {
  971. data: newAcc.publicKey,
  972. systemProgram: anchor.web3.SystemProgram.programId,
  973. payer: program.provider.wallet.publicKey,
  974. },
  975. signers: [newAcc],
  976. });
  977. assert.ok(false);
  978. } catch (_err) {
  979. assert.isTrue(_err instanceof AnchorError);
  980. const err: AnchorError = _err;
  981. assert.strictEqual(err.error.errorCode.number, 2019);
  982. }
  983. });
  984. it("init_if_needed throws if mint exists but has the wrong mint authority", async () => {
  985. const mint = anchor.web3.Keypair.generate();
  986. await program.rpc.testInitMint({
  987. accounts: {
  988. mint: mint.publicKey,
  989. payer: program.provider.wallet.publicKey,
  990. systemProgram: anchor.web3.SystemProgram.programId,
  991. tokenProgram: TOKEN_PROGRAM_ID,
  992. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  993. },
  994. signers: [mint],
  995. });
  996. try {
  997. await program.rpc.testInitMintIfNeeded(6, {
  998. accounts: {
  999. mint: mint.publicKey,
  1000. payer: program.provider.wallet.publicKey,
  1001. systemProgram: anchor.web3.SystemProgram.programId,
  1002. tokenProgram: TOKEN_PROGRAM_ID,
  1003. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1004. mintAuthority: anchor.web3.Keypair.generate().publicKey,
  1005. freezeAuthority: program.provider.wallet.publicKey,
  1006. },
  1007. signers: [mint],
  1008. });
  1009. assert.ok(false);
  1010. } catch (_err) {
  1011. assert.isTrue(_err instanceof AnchorError);
  1012. const err: AnchorError = _err;
  1013. assert.strictEqual(err.error.errorCode.number, 2016);
  1014. }
  1015. });
  1016. it("init_if_needed throws if mint exists but has the wrong freeze authority", async () => {
  1017. const mint = anchor.web3.Keypair.generate();
  1018. await program.rpc.testInitMint({
  1019. accounts: {
  1020. mint: mint.publicKey,
  1021. payer: program.provider.wallet.publicKey,
  1022. systemProgram: anchor.web3.SystemProgram.programId,
  1023. tokenProgram: TOKEN_PROGRAM_ID,
  1024. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1025. },
  1026. signers: [mint],
  1027. });
  1028. try {
  1029. await program.rpc.testInitMintIfNeeded(6, {
  1030. accounts: {
  1031. mint: mint.publicKey,
  1032. payer: program.provider.wallet.publicKey,
  1033. systemProgram: anchor.web3.SystemProgram.programId,
  1034. tokenProgram: TOKEN_PROGRAM_ID,
  1035. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1036. mintAuthority: program.provider.wallet.publicKey,
  1037. freezeAuthority: anchor.web3.Keypair.generate().publicKey,
  1038. },
  1039. signers: [mint],
  1040. });
  1041. assert.ok(false);
  1042. } catch (_err) {
  1043. assert.isTrue(_err instanceof AnchorError);
  1044. const err: AnchorError = _err;
  1045. assert.strictEqual(err.error.errorCode.number, 2017);
  1046. }
  1047. });
  1048. it("init_if_needed throws if mint exists but has the wrong decimals", async () => {
  1049. const mint = anchor.web3.Keypair.generate();
  1050. await program.rpc.testInitMint({
  1051. accounts: {
  1052. mint: mint.publicKey,
  1053. payer: program.provider.wallet.publicKey,
  1054. systemProgram: anchor.web3.SystemProgram.programId,
  1055. tokenProgram: TOKEN_PROGRAM_ID,
  1056. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1057. },
  1058. signers: [mint],
  1059. });
  1060. try {
  1061. await program.rpc.testInitMintIfNeeded(9, {
  1062. accounts: {
  1063. mint: mint.publicKey,
  1064. payer: program.provider.wallet.publicKey,
  1065. systemProgram: anchor.web3.SystemProgram.programId,
  1066. tokenProgram: TOKEN_PROGRAM_ID,
  1067. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1068. mintAuthority: program.provider.wallet.publicKey,
  1069. freezeAuthority: program.provider.wallet.publicKey,
  1070. },
  1071. signers: [mint],
  1072. });
  1073. assert.ok(false);
  1074. } catch (_err) {
  1075. assert.isTrue(_err instanceof AnchorError);
  1076. const err: AnchorError = _err;
  1077. assert.strictEqual(err.error.errorCode.number, 2018);
  1078. }
  1079. });
  1080. it("init_if_needed throws if token exists but has the wrong owner", async () => {
  1081. const mint = anchor.web3.Keypair.generate();
  1082. await program.rpc.testInitMint({
  1083. accounts: {
  1084. mint: mint.publicKey,
  1085. payer: program.provider.wallet.publicKey,
  1086. systemProgram: anchor.web3.SystemProgram.programId,
  1087. tokenProgram: TOKEN_PROGRAM_ID,
  1088. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1089. },
  1090. signers: [mint],
  1091. });
  1092. const token = anchor.web3.Keypair.generate();
  1093. await program.rpc.testInitToken({
  1094. accounts: {
  1095. token: token.publicKey,
  1096. mint: mint.publicKey,
  1097. payer: program.provider.wallet.publicKey,
  1098. systemProgram: anchor.web3.SystemProgram.programId,
  1099. tokenProgram: TOKEN_PROGRAM_ID,
  1100. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1101. },
  1102. signers: [token],
  1103. });
  1104. try {
  1105. await program.rpc.testInitTokenIfNeeded({
  1106. accounts: {
  1107. token: token.publicKey,
  1108. mint: mint.publicKey,
  1109. payer: program.provider.wallet.publicKey,
  1110. systemProgram: anchor.web3.SystemProgram.programId,
  1111. tokenProgram: TOKEN_PROGRAM_ID,
  1112. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1113. authority: anchor.web3.Keypair.generate().publicKey,
  1114. },
  1115. signers: [token],
  1116. });
  1117. assert.ok(false);
  1118. } catch (_err) {
  1119. assert.isTrue(_err instanceof AnchorError);
  1120. const err: AnchorError = _err;
  1121. assert.strictEqual(err.error.errorCode.number, 2015);
  1122. }
  1123. });
  1124. it("init_if_needed throws if token exists but has the wrong mint", async () => {
  1125. const mint = anchor.web3.Keypair.generate();
  1126. await program.rpc.testInitMint({
  1127. accounts: {
  1128. mint: mint.publicKey,
  1129. payer: program.provider.wallet.publicKey,
  1130. systemProgram: anchor.web3.SystemProgram.programId,
  1131. tokenProgram: TOKEN_PROGRAM_ID,
  1132. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1133. },
  1134. signers: [mint],
  1135. });
  1136. const mint2 = anchor.web3.Keypair.generate();
  1137. await program.rpc.testInitMint({
  1138. accounts: {
  1139. mint: mint2.publicKey,
  1140. payer: program.provider.wallet.publicKey,
  1141. systemProgram: anchor.web3.SystemProgram.programId,
  1142. tokenProgram: TOKEN_PROGRAM_ID,
  1143. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1144. },
  1145. signers: [mint2],
  1146. });
  1147. const token = anchor.web3.Keypair.generate();
  1148. await program.rpc.testInitToken({
  1149. accounts: {
  1150. token: token.publicKey,
  1151. mint: mint.publicKey,
  1152. payer: program.provider.wallet.publicKey,
  1153. systemProgram: anchor.web3.SystemProgram.programId,
  1154. tokenProgram: TOKEN_PROGRAM_ID,
  1155. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1156. },
  1157. signers: [token],
  1158. });
  1159. try {
  1160. await program.rpc.testInitTokenIfNeeded({
  1161. accounts: {
  1162. token: token.publicKey,
  1163. mint: mint2.publicKey,
  1164. payer: program.provider.wallet.publicKey,
  1165. systemProgram: anchor.web3.SystemProgram.programId,
  1166. tokenProgram: TOKEN_PROGRAM_ID,
  1167. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1168. authority: program.provider.wallet.publicKey,
  1169. },
  1170. signers: [token],
  1171. });
  1172. assert.ok(false);
  1173. } catch (_err) {
  1174. assert.isTrue(_err instanceof AnchorError);
  1175. const err: AnchorError = _err;
  1176. assert.strictEqual(err.error.errorCode.number, 2014);
  1177. }
  1178. });
  1179. it("init_if_needed throws if associated token exists but has the wrong owner", async () => {
  1180. const mint = Keypair.generate();
  1181. await program.rpc.testInitMint({
  1182. accounts: {
  1183. mint: mint.publicKey,
  1184. payer: program.provider.wallet.publicKey,
  1185. systemProgram: SystemProgram.programId,
  1186. tokenProgram: TOKEN_PROGRAM_ID,
  1187. rent: SYSVAR_RENT_PUBKEY,
  1188. },
  1189. signers: [mint],
  1190. });
  1191. const associatedToken = await Token.getAssociatedTokenAddress(
  1192. ASSOCIATED_TOKEN_PROGRAM_ID,
  1193. TOKEN_PROGRAM_ID,
  1194. mint.publicKey,
  1195. program.provider.wallet.publicKey
  1196. );
  1197. await program.rpc.testInitAssociatedToken({
  1198. accounts: {
  1199. token: associatedToken,
  1200. mint: mint.publicKey,
  1201. payer: program.provider.wallet.publicKey,
  1202. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1203. systemProgram: anchor.web3.SystemProgram.programId,
  1204. tokenProgram: TOKEN_PROGRAM_ID,
  1205. associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
  1206. },
  1207. });
  1208. try {
  1209. await program.rpc.testInitAssociatedTokenIfNeeded({
  1210. accounts: {
  1211. token: associatedToken,
  1212. mint: mint.publicKey,
  1213. payer: program.provider.wallet.publicKey,
  1214. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1215. systemProgram: anchor.web3.SystemProgram.programId,
  1216. tokenProgram: TOKEN_PROGRAM_ID,
  1217. associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
  1218. authority: anchor.web3.Keypair.generate().publicKey,
  1219. },
  1220. });
  1221. assert.ok(false);
  1222. } catch (_err) {
  1223. assert.isTrue(_err instanceof AnchorError);
  1224. const err: AnchorError = _err;
  1225. assert.strictEqual(err.error.errorCode.number, 2015);
  1226. }
  1227. });
  1228. it("init_if_needed throws if associated token exists but has the wrong mint", async () => {
  1229. const mint = anchor.web3.Keypair.generate();
  1230. await program.rpc.testInitMint({
  1231. accounts: {
  1232. mint: mint.publicKey,
  1233. payer: program.provider.wallet.publicKey,
  1234. systemProgram: anchor.web3.SystemProgram.programId,
  1235. tokenProgram: TOKEN_PROGRAM_ID,
  1236. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1237. },
  1238. signers: [mint],
  1239. });
  1240. const mint2 = anchor.web3.Keypair.generate();
  1241. await program.rpc.testInitMint({
  1242. accounts: {
  1243. mint: mint2.publicKey,
  1244. payer: program.provider.wallet.publicKey,
  1245. systemProgram: anchor.web3.SystemProgram.programId,
  1246. tokenProgram: TOKEN_PROGRAM_ID,
  1247. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1248. },
  1249. signers: [mint2],
  1250. });
  1251. const associatedToken = await Token.getAssociatedTokenAddress(
  1252. ASSOCIATED_TOKEN_PROGRAM_ID,
  1253. TOKEN_PROGRAM_ID,
  1254. mint.publicKey,
  1255. program.provider.wallet.publicKey
  1256. );
  1257. await program.rpc.testInitAssociatedToken({
  1258. accounts: {
  1259. token: associatedToken,
  1260. mint: mint.publicKey,
  1261. payer: program.provider.wallet.publicKey,
  1262. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1263. systemProgram: anchor.web3.SystemProgram.programId,
  1264. tokenProgram: TOKEN_PROGRAM_ID,
  1265. associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
  1266. },
  1267. });
  1268. try {
  1269. await program.rpc.testInitAssociatedTokenIfNeeded({
  1270. accounts: {
  1271. token: associatedToken,
  1272. mint: mint2.publicKey,
  1273. payer: program.provider.wallet.publicKey,
  1274. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1275. systemProgram: anchor.web3.SystemProgram.programId,
  1276. tokenProgram: TOKEN_PROGRAM_ID,
  1277. associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
  1278. authority: program.provider.wallet.publicKey,
  1279. },
  1280. });
  1281. assert.ok(false);
  1282. } catch (_err) {
  1283. assert.isTrue(_err instanceof AnchorError);
  1284. const err: AnchorError = _err;
  1285. assert.strictEqual(err.error.errorCode.number, 2014);
  1286. }
  1287. });
  1288. it("init_if_needed throws if token exists with correct owner and mint but is not the ATA", async () => {
  1289. const mint = anchor.web3.Keypair.generate();
  1290. await program.rpc.testInitMint({
  1291. accounts: {
  1292. mint: mint.publicKey,
  1293. payer: program.provider.wallet.publicKey,
  1294. systemProgram: anchor.web3.SystemProgram.programId,
  1295. tokenProgram: TOKEN_PROGRAM_ID,
  1296. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1297. },
  1298. signers: [mint],
  1299. });
  1300. const associatedToken = await Token.getAssociatedTokenAddress(
  1301. ASSOCIATED_TOKEN_PROGRAM_ID,
  1302. TOKEN_PROGRAM_ID,
  1303. mint.publicKey,
  1304. program.provider.wallet.publicKey
  1305. );
  1306. await program.rpc.testInitAssociatedToken({
  1307. accounts: {
  1308. token: associatedToken,
  1309. mint: mint.publicKey,
  1310. payer: program.provider.wallet.publicKey,
  1311. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1312. systemProgram: anchor.web3.SystemProgram.programId,
  1313. tokenProgram: TOKEN_PROGRAM_ID,
  1314. associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
  1315. },
  1316. });
  1317. const token = anchor.web3.Keypair.generate();
  1318. await program.rpc.testInitToken({
  1319. accounts: {
  1320. token: token.publicKey,
  1321. mint: mint.publicKey,
  1322. payer: program.provider.wallet.publicKey,
  1323. systemProgram: anchor.web3.SystemProgram.programId,
  1324. tokenProgram: TOKEN_PROGRAM_ID,
  1325. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1326. },
  1327. signers: [token],
  1328. });
  1329. try {
  1330. await program.rpc.testInitAssociatedTokenIfNeeded({
  1331. accounts: {
  1332. token: token.publicKey,
  1333. mint: mint.publicKey,
  1334. payer: program.provider.wallet.publicKey,
  1335. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1336. systemProgram: anchor.web3.SystemProgram.programId,
  1337. tokenProgram: TOKEN_PROGRAM_ID,
  1338. associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
  1339. authority: program.provider.wallet.publicKey,
  1340. },
  1341. });
  1342. assert.ok(false);
  1343. } catch (_err) {
  1344. assert.isTrue(_err instanceof AnchorError);
  1345. const err: AnchorError = _err;
  1346. assert.strictEqual(err.error.errorCode.number, 3014);
  1347. }
  1348. });
  1349. it("Can use multidimensional array", async () => {
  1350. const array2d = new Array(10).fill(new Array(10).fill(99));
  1351. const data = anchor.web3.Keypair.generate();
  1352. await program.rpc.testMultidimensionalArray(array2d, {
  1353. accounts: {
  1354. data: data.publicKey,
  1355. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1356. },
  1357. signers: [data],
  1358. instructions: [
  1359. await program.account.dataMultidimensionalArray.createInstruction(data),
  1360. ],
  1361. });
  1362. const dataAccount = await program.account.dataMultidimensionalArray.fetch(
  1363. data.publicKey
  1364. );
  1365. assert.deepStrictEqual(dataAccount.data, array2d);
  1366. });
  1367. it("Can use multidimensional array with const sizes", async () => {
  1368. const array2d = new Array(10).fill(new Array(11).fill(22));
  1369. const data = anchor.web3.Keypair.generate();
  1370. await program.rpc.testMultidimensionalArrayConstSizes(array2d, {
  1371. accounts: {
  1372. data: data.publicKey,
  1373. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  1374. },
  1375. signers: [data],
  1376. instructions: [
  1377. await program.account.dataMultidimensionalArrayConstSizes.createInstruction(
  1378. data
  1379. ),
  1380. ],
  1381. });
  1382. const dataAccount =
  1383. await program.account.dataMultidimensionalArrayConstSizes.fetch(
  1384. data.publicKey
  1385. );
  1386. assert.deepStrictEqual(dataAccount.data, array2d);
  1387. });
  1388. describe("Can validate PDAs derived from other program ids", () => {
  1389. it("With bumps using create_program_address", async () => {
  1390. const [firstPDA, firstBump] =
  1391. await anchor.web3.PublicKey.findProgramAddress(
  1392. [anchor.utils.bytes.utf8.encode("seed")],
  1393. ASSOCIATED_TOKEN_PROGRAM_ID
  1394. );
  1395. const [secondPDA, secondBump] =
  1396. await anchor.web3.PublicKey.findProgramAddress(
  1397. [anchor.utils.bytes.utf8.encode("seed")],
  1398. program.programId
  1399. );
  1400. // correct bump but wrong address
  1401. const wrongAddress = anchor.web3.Keypair.generate().publicKey;
  1402. try {
  1403. await program.rpc.testProgramIdConstraint(firstBump, secondBump, {
  1404. accounts: {
  1405. first: wrongAddress,
  1406. second: secondPDA,
  1407. },
  1408. });
  1409. assert.ok(false);
  1410. } catch (_err) {
  1411. assert.isTrue(_err instanceof AnchorError);
  1412. const err: AnchorError = _err;
  1413. assert.strictEqual(err.error.errorCode.number, 2006);
  1414. }
  1415. // matching bump seed for wrong address but derived from wrong program
  1416. try {
  1417. await program.rpc.testProgramIdConstraint(secondBump, secondBump, {
  1418. accounts: {
  1419. first: secondPDA,
  1420. second: secondPDA,
  1421. },
  1422. });
  1423. assert.ok(false);
  1424. } catch (_err) {
  1425. assert.isTrue(_err instanceof AnchorError);
  1426. const err: AnchorError = _err;
  1427. assert.strictEqual(err.error.errorCode.number, 2006);
  1428. }
  1429. // correct inputs should lead to successful tx
  1430. await program.rpc.testProgramIdConstraint(firstBump, secondBump, {
  1431. accounts: {
  1432. first: firstPDA,
  1433. second: secondPDA,
  1434. },
  1435. });
  1436. });
  1437. it("With bumps using find_program_address", async () => {
  1438. const firstPDA = (
  1439. await anchor.web3.PublicKey.findProgramAddress(
  1440. [anchor.utils.bytes.utf8.encode("seed")],
  1441. ASSOCIATED_TOKEN_PROGRAM_ID
  1442. )
  1443. )[0];
  1444. const secondPDA = (
  1445. await anchor.web3.PublicKey.findProgramAddress(
  1446. [anchor.utils.bytes.utf8.encode("seed")],
  1447. program.programId
  1448. )
  1449. )[0];
  1450. // random wrong address
  1451. const wrongAddress = anchor.web3.Keypair.generate().publicKey;
  1452. try {
  1453. await program.rpc.testProgramIdConstraintFindPda({
  1454. accounts: {
  1455. first: wrongAddress,
  1456. second: secondPDA,
  1457. },
  1458. });
  1459. assert.ok(false);
  1460. } catch (_err) {
  1461. assert.isTrue(_err instanceof AnchorError);
  1462. const err: AnchorError = _err;
  1463. assert.strictEqual(err.error.errorCode.number, 2006);
  1464. }
  1465. // same seeds but derived from wrong program
  1466. try {
  1467. await program.rpc.testProgramIdConstraintFindPda({
  1468. accounts: {
  1469. first: secondPDA,
  1470. second: secondPDA,
  1471. },
  1472. });
  1473. assert.ok(false);
  1474. } catch (_err) {
  1475. assert.isTrue(_err instanceof AnchorError);
  1476. const err: AnchorError = _err;
  1477. assert.strictEqual(err.error.errorCode.number, 2006);
  1478. }
  1479. // correct inputs should lead to successful tx
  1480. await program.rpc.testProgramIdConstraintFindPda({
  1481. accounts: {
  1482. first: firstPDA,
  1483. second: secondPDA,
  1484. },
  1485. });
  1486. });
  1487. });
  1488. });