misc.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  1. const anchor = require("@project-serum/anchor");
  2. const PublicKey = anchor.web3.PublicKey;
  3. const assert = require("assert");
  4. const { TOKEN_PROGRAM_ID, Token } = require("@solana/spl-token");
  5. describe("misc", () => {
  6. // Configure the client to use the local cluster.
  7. anchor.setProvider(anchor.Provider.env());
  8. const program = anchor.workspace.Misc;
  9. const misc2Program = anchor.workspace.Misc2;
  10. it("Can allocate extra space for a state constructor", async () => {
  11. const tx = await program.state.rpc.new();
  12. const addr = await program.state.address();
  13. const state = await program.state.fetch();
  14. const accountInfo = await program.provider.connection.getAccountInfo(addr);
  15. assert.ok(state.v.equals(Buffer.from([])));
  16. assert.ok(accountInfo.data.length === 99);
  17. });
  18. it("Can use remaining accounts for a state instruction", async () => {
  19. await program.state.rpc.remainingAccounts({
  20. remainingAccounts: [
  21. { pubkey: misc2Program.programId, isWritable: false, isSigner: false },
  22. ],
  23. });
  24. });
  25. const data = anchor.web3.Keypair.generate();
  26. it("Can use u128 and i128", async () => {
  27. const tx = await program.rpc.initialize(
  28. new anchor.BN(1234),
  29. new anchor.BN(22),
  30. {
  31. accounts: {
  32. data: data.publicKey,
  33. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  34. },
  35. signers: [data],
  36. instructions: [await program.account.data.createInstruction(data)],
  37. }
  38. );
  39. const dataAccount = await program.account.data.fetch(data.publicKey);
  40. assert.ok(dataAccount.udata.eq(new anchor.BN(1234)));
  41. assert.ok(dataAccount.idata.eq(new anchor.BN(22)));
  42. });
  43. it("Can use u16", async () => {
  44. const data = anchor.web3.Keypair.generate();
  45. const tx = await program.rpc.testU16(99, {
  46. accounts: {
  47. myAccount: data.publicKey,
  48. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  49. },
  50. signers: [data],
  51. instructions: [await program.account.dataU16.createInstruction(data)],
  52. });
  53. const dataAccount = await program.account.dataU16.fetch(data.publicKey);
  54. assert.ok(dataAccount.data === 99);
  55. });
  56. it("Can embed programs into genesis from the Anchor.toml", async () => {
  57. const pid = new anchor.web3.PublicKey(
  58. "FtMNMKp9DZHKWUyVAsj3Q5QV8ow4P3fUPP7ZrWEQJzKr"
  59. );
  60. let accInfo = await anchor.getProvider().connection.getAccountInfo(pid);
  61. assert.ok(accInfo.executable);
  62. });
  63. it("Can use the owner constraint", async () => {
  64. await program.rpc.testOwner({
  65. accounts: {
  66. data: data.publicKey,
  67. misc: program.programId,
  68. },
  69. });
  70. await assert.rejects(
  71. async () => {
  72. await program.rpc.testOwner({
  73. accounts: {
  74. data: program.provider.wallet.publicKey,
  75. misc: program.programId,
  76. },
  77. });
  78. },
  79. (err) => {
  80. return true;
  81. }
  82. );
  83. });
  84. it("Can use the executable attribute", async () => {
  85. await program.rpc.testExecutable({
  86. accounts: {
  87. program: program.programId,
  88. },
  89. });
  90. await assert.rejects(
  91. async () => {
  92. await program.rpc.testExecutable({
  93. accounts: {
  94. program: program.provider.wallet.publicKey,
  95. },
  96. });
  97. },
  98. (err) => {
  99. return true;
  100. }
  101. );
  102. });
  103. it("Can CPI to state instructions", async () => {
  104. const oldData = new anchor.BN(0);
  105. await misc2Program.state.rpc.new({
  106. accounts: {
  107. authority: program.provider.wallet.publicKey,
  108. },
  109. });
  110. let stateAccount = await misc2Program.state.fetch();
  111. assert.ok(stateAccount.data.eq(oldData));
  112. assert.ok(stateAccount.auth.equals(program.provider.wallet.publicKey));
  113. const newData = new anchor.BN(2134);
  114. await program.rpc.testStateCpi(newData, {
  115. accounts: {
  116. authority: program.provider.wallet.publicKey,
  117. cpiState: await misc2Program.state.address(),
  118. misc2Program: misc2Program.programId,
  119. },
  120. });
  121. stateAccount = await misc2Program.state.fetch();
  122. assert.ok(stateAccount.data.eq(newData));
  123. assert.ok(stateAccount.auth.equals(program.provider.wallet.publicKey));
  124. });
  125. it("Can retrieve events when simulating a transaction", async () => {
  126. const resp = await program.simulate.testSimulate(44);
  127. const expectedRaw = [
  128. "Program Z2Ddx1Lcd8CHTV9tkWtNnFQrSz6kxz2H38wrr18zZRZ invoke [1]",
  129. "Program log: NgyCA9omwbMsAAAA",
  130. "Program log: fPhuIELK/k7SBAAA",
  131. "Program log: jvbowsvlmkcJAAAA",
  132. "Program Z2Ddx1Lcd8CHTV9tkWtNnFQrSz6kxz2H38wrr18zZRZ consumed 4819 of 200000 compute units",
  133. "Program Z2Ddx1Lcd8CHTV9tkWtNnFQrSz6kxz2H38wrr18zZRZ success",
  134. ];
  135. assert.ok(JSON.stringify(expectedRaw), resp.raw);
  136. assert.ok(resp.events[0].name === "E1");
  137. assert.ok(resp.events[0].data.data === 44);
  138. assert.ok(resp.events[1].name === "E2");
  139. assert.ok(resp.events[1].data.data === 1234);
  140. assert.ok(resp.events[2].name === "E3");
  141. assert.ok(resp.events[2].data.data === 9);
  142. });
  143. it("Can use i8 in the idl", async () => {
  144. const data = anchor.web3.Keypair.generate();
  145. await program.rpc.testI8(-3, {
  146. accounts: {
  147. data: data.publicKey,
  148. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  149. },
  150. instructions: [await program.account.dataI8.createInstruction(data)],
  151. signers: [data],
  152. });
  153. const dataAccount = await program.account.dataI8.fetch(data.publicKey);
  154. assert.ok(dataAccount.data === -3);
  155. });
  156. let dataPubkey;
  157. it("Can use i16 in the idl", async () => {
  158. const data = anchor.web3.Keypair.generate();
  159. await program.rpc.testI16(-2048, {
  160. accounts: {
  161. data: data.publicKey,
  162. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  163. },
  164. instructions: [await program.account.dataI16.createInstruction(data)],
  165. signers: [data],
  166. });
  167. const dataAccount = await program.account.dataI16.fetch(data.publicKey);
  168. assert.ok(dataAccount.data === -2048);
  169. dataPubkey = data.publicKey;
  170. });
  171. it("Can use base58 strings to fetch an account", async () => {
  172. const dataAccount = await program.account.dataI16.fetch(
  173. dataPubkey.toString()
  174. );
  175. assert.ok(dataAccount.data === -2048);
  176. });
  177. it("Should fail to close an account when sending lamports to itself", async () => {
  178. try {
  179. await program.rpc.testClose({
  180. accounts: {
  181. data: data.publicKey,
  182. solDest: data.publicKey,
  183. },
  184. });
  185. assert.ok(false);
  186. } catch (err) {
  187. const errMsg = "A close constraint was violated";
  188. assert.equal(err.toString(), errMsg);
  189. assert.equal(err.msg, errMsg);
  190. assert.equal(err.code, 151);
  191. }
  192. });
  193. it("Can close an account", async () => {
  194. const openAccount = await program.provider.connection.getAccountInfo(
  195. data.publicKey
  196. );
  197. assert.ok(openAccount !== null);
  198. let beforeBalance = (
  199. await program.provider.connection.getAccountInfo(
  200. program.provider.wallet.publicKey
  201. )
  202. ).lamports;
  203. await program.rpc.testClose({
  204. accounts: {
  205. data: data.publicKey,
  206. solDest: program.provider.wallet.publicKey,
  207. },
  208. });
  209. let afterBalance = (
  210. await program.provider.connection.getAccountInfo(
  211. program.provider.wallet.publicKey
  212. )
  213. ).lamports;
  214. // Retrieved rent exemption sol.
  215. assert.ok(afterBalance > beforeBalance);
  216. const closedAccount = await program.provider.connection.getAccountInfo(
  217. data.publicKey
  218. );
  219. assert.ok(closedAccount === null);
  220. });
  221. it("Can use instruction data in accounts constraints", async () => {
  222. // b"my-seed"
  223. const seed = Buffer.from([109, 121, 45, 115, 101, 101, 100]);
  224. const [myPda, nonce] = await PublicKey.findProgramAddress(
  225. [seed, anchor.web3.SYSVAR_RENT_PUBKEY.toBuffer()],
  226. program.programId
  227. );
  228. await program.rpc.testInstructionConstraint(nonce, {
  229. accounts: {
  230. myPda,
  231. myAccount: anchor.web3.SYSVAR_RENT_PUBKEY,
  232. },
  233. });
  234. });
  235. it("Can create a PDA account with instruction data", async () => {
  236. const seed = Buffer.from([1, 2, 3, 4]);
  237. const domain = "my-domain";
  238. const foo = anchor.web3.SYSVAR_RENT_PUBKEY;
  239. const [myPda, nonce] = await PublicKey.findProgramAddress(
  240. [
  241. Buffer.from(anchor.utils.bytes.utf8.encode("my-seed")),
  242. Buffer.from(anchor.utils.bytes.utf8.encode(domain)),
  243. foo.toBuffer(),
  244. seed,
  245. ],
  246. program.programId
  247. );
  248. await program.rpc.testPdaInit(domain, seed, nonce, {
  249. accounts: {
  250. myPda,
  251. myPayer: program.provider.wallet.publicKey,
  252. foo,
  253. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  254. systemProgram: anchor.web3.SystemProgram.programId,
  255. },
  256. });
  257. const myPdaAccount = await program.account.dataU16.fetch(myPda);
  258. assert.ok(myPdaAccount.data === 6);
  259. });
  260. it("Can create a zero copy PDA account", async () => {
  261. const [myPda, nonce] = await PublicKey.findProgramAddress(
  262. [Buffer.from(anchor.utils.bytes.utf8.encode("my-seed"))],
  263. program.programId
  264. );
  265. await program.rpc.testPdaInitZeroCopy(nonce, {
  266. accounts: {
  267. myPda,
  268. myPayer: program.provider.wallet.publicKey,
  269. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  270. systemProgram: anchor.web3.SystemProgram.programId,
  271. },
  272. });
  273. const myPdaAccount = await program.account.dataZeroCopy.fetch(myPda);
  274. assert.ok(myPdaAccount.data === 9);
  275. assert.ok((myPdaAccount.bump = nonce));
  276. });
  277. it("Can write to a zero copy PDA account", async () => {
  278. const [myPda, bump] = await PublicKey.findProgramAddress(
  279. [Buffer.from(anchor.utils.bytes.utf8.encode("my-seed"))],
  280. program.programId
  281. );
  282. await program.rpc.testPdaMutZeroCopy({
  283. accounts: {
  284. myPda,
  285. myPayer: program.provider.wallet.publicKey,
  286. },
  287. });
  288. const myPdaAccount = await program.account.dataZeroCopy.fetch(myPda);
  289. assert.ok(myPdaAccount.data === 1234);
  290. assert.ok((myPdaAccount.bump = bump));
  291. });
  292. it("Can create a token account from seeds pda", async () => {
  293. const [mint, mint_bump] = await PublicKey.findProgramAddress(
  294. [Buffer.from(anchor.utils.bytes.utf8.encode("my-mint-seed"))],
  295. program.programId
  296. );
  297. const [myPda, token_bump] = await PublicKey.findProgramAddress(
  298. [Buffer.from(anchor.utils.bytes.utf8.encode("my-token-seed"))],
  299. program.programId
  300. );
  301. await program.rpc.testTokenSeedsInit(token_bump, mint_bump, {
  302. accounts: {
  303. myPda,
  304. mint,
  305. authority: program.provider.wallet.publicKey,
  306. systemProgram: anchor.web3.SystemProgram.programId,
  307. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  308. tokenProgram: TOKEN_PROGRAM_ID,
  309. },
  310. });
  311. const mintAccount = new Token(
  312. program.provider.connection,
  313. mint,
  314. TOKEN_PROGRAM_ID,
  315. program.provider.wallet.payer
  316. );
  317. const account = await mintAccount.getAccountInfo(myPda);
  318. assert.ok(account.state === 1);
  319. assert.ok(account.amount.toNumber() === 0);
  320. assert.ok(account.isInitialized);
  321. assert.ok(account.owner.equals(program.provider.wallet.publicKey));
  322. assert.ok(account.mint.equals(mint));
  323. });
  324. it("Can execute a fallback function", async () => {
  325. await assert.rejects(
  326. async () => {
  327. await anchor.utils.rpc.invoke(program.programId);
  328. },
  329. (err) => {
  330. assert.ok(err.toString().includes("custom program error: 0x4d2"));
  331. return true;
  332. }
  333. );
  334. });
  335. it("Can init a random account", async () => {
  336. const data = anchor.web3.Keypair.generate();
  337. await program.rpc.testInit({
  338. accounts: {
  339. data: data.publicKey,
  340. payer: program.provider.wallet.publicKey,
  341. systemProgram: anchor.web3.SystemProgram.programId,
  342. },
  343. signers: [data],
  344. });
  345. const account = await program.account.dataI8.fetch(data.publicKey);
  346. assert.ok(account.data === 3);
  347. });
  348. it("Can init a random account prefunded", async () => {
  349. const data = anchor.web3.Keypair.generate();
  350. await program.rpc.testInit({
  351. accounts: {
  352. data: data.publicKey,
  353. payer: program.provider.wallet.publicKey,
  354. systemProgram: anchor.web3.SystemProgram.programId,
  355. },
  356. signers: [data],
  357. instructions: [
  358. anchor.web3.SystemProgram.transfer({
  359. fromPubkey: program.provider.wallet.publicKey,
  360. toPubkey: data.publicKey,
  361. lamports: 4039280,
  362. }),
  363. ],
  364. });
  365. const account = await program.account.dataI8.fetch(data.publicKey);
  366. assert.ok(account.data === 3);
  367. });
  368. it("Can init a random zero copy account", async () => {
  369. const data = anchor.web3.Keypair.generate();
  370. await program.rpc.testInitZeroCopy({
  371. accounts: {
  372. data: data.publicKey,
  373. payer: program.provider.wallet.publicKey,
  374. systemProgram: anchor.web3.SystemProgram.programId,
  375. },
  376. signers: [data],
  377. });
  378. const account = await program.account.dataZeroCopy.fetch(data.publicKey);
  379. assert.ok(account.data === 10);
  380. assert.ok(account.bump === 2);
  381. });
  382. let mint = undefined;
  383. it("Can create a random mint account", async () => {
  384. mint = anchor.web3.Keypair.generate();
  385. await program.rpc.testInitMint({
  386. accounts: {
  387. mint: mint.publicKey,
  388. payer: program.provider.wallet.publicKey,
  389. systemProgram: anchor.web3.SystemProgram.programId,
  390. tokenProgram: TOKEN_PROGRAM_ID,
  391. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  392. },
  393. signers: [mint],
  394. });
  395. const client = new Token(
  396. program.provider.connection,
  397. mint.publicKey,
  398. TOKEN_PROGRAM_ID,
  399. program.provider.wallet.payer
  400. );
  401. const mintAccount = await client.getMintInfo();
  402. assert.ok(mintAccount.decimals === 6);
  403. assert.ok(
  404. mintAccount.mintAuthority.equals(program.provider.wallet.publicKey)
  405. );
  406. });
  407. it("Can create a random mint account prefunded", async () => {
  408. mint = anchor.web3.Keypair.generate();
  409. await program.rpc.testInitMint({
  410. accounts: {
  411. mint: mint.publicKey,
  412. payer: program.provider.wallet.publicKey,
  413. systemProgram: anchor.web3.SystemProgram.programId,
  414. tokenProgram: TOKEN_PROGRAM_ID,
  415. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  416. },
  417. signers: [mint],
  418. instructions: [
  419. anchor.web3.SystemProgram.transfer({
  420. fromPubkey: program.provider.wallet.publicKey,
  421. toPubkey: mint.publicKey,
  422. lamports: 4039280,
  423. }),
  424. ],
  425. });
  426. const client = new Token(
  427. program.provider.connection,
  428. mint.publicKey,
  429. TOKEN_PROGRAM_ID,
  430. program.provider.wallet.payer
  431. );
  432. const mintAccount = await client.getMintInfo();
  433. assert.ok(mintAccount.decimals === 6);
  434. assert.ok(
  435. mintAccount.mintAuthority.equals(program.provider.wallet.publicKey)
  436. );
  437. });
  438. it("Can create a random token account", async () => {
  439. const token = anchor.web3.Keypair.generate();
  440. await program.rpc.testInitToken({
  441. accounts: {
  442. token: token.publicKey,
  443. mint: mint.publicKey,
  444. payer: program.provider.wallet.publicKey,
  445. systemProgram: anchor.web3.SystemProgram.programId,
  446. tokenProgram: TOKEN_PROGRAM_ID,
  447. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  448. },
  449. signers: [token],
  450. });
  451. const client = new Token(
  452. program.provider.connection,
  453. mint.publicKey,
  454. TOKEN_PROGRAM_ID,
  455. program.provider.wallet.payer
  456. );
  457. const account = await client.getAccountInfo(token.publicKey);
  458. assert.ok(account.state === 1);
  459. assert.ok(account.amount.toNumber() === 0);
  460. assert.ok(account.isInitialized);
  461. assert.ok(account.owner.equals(program.provider.wallet.publicKey));
  462. assert.ok(account.mint.equals(mint.publicKey));
  463. });
  464. it("Can create a random token with prefunding", async () => {
  465. const token = anchor.web3.Keypair.generate();
  466. await program.rpc.testInitToken({
  467. accounts: {
  468. token: token.publicKey,
  469. mint: mint.publicKey,
  470. payer: program.provider.wallet.publicKey,
  471. systemProgram: anchor.web3.SystemProgram.programId,
  472. tokenProgram: TOKEN_PROGRAM_ID,
  473. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  474. },
  475. signers: [token],
  476. instructions: [
  477. anchor.web3.SystemProgram.transfer({
  478. fromPubkey: program.provider.wallet.publicKey,
  479. toPubkey: token.publicKey,
  480. lamports: 4039280,
  481. }),
  482. ],
  483. });
  484. const client = new Token(
  485. program.provider.connection,
  486. mint.publicKey,
  487. TOKEN_PROGRAM_ID,
  488. program.provider.wallet.payer
  489. );
  490. const account = await client.getAccountInfo(token.publicKey);
  491. assert.ok(account.state === 1);
  492. assert.ok(account.amount.toNumber() === 0);
  493. assert.ok(account.isInitialized);
  494. assert.ok(account.owner.equals(program.provider.wallet.publicKey));
  495. assert.ok(account.mint.equals(mint.publicKey));
  496. });
  497. it("Can create a random token with prefunding under the rent exemption", async () => {
  498. const token = anchor.web3.Keypair.generate();
  499. await program.rpc.testInitToken({
  500. accounts: {
  501. token: token.publicKey,
  502. mint: mint.publicKey,
  503. payer: program.provider.wallet.publicKey,
  504. systemProgram: anchor.web3.SystemProgram.programId,
  505. tokenProgram: TOKEN_PROGRAM_ID,
  506. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  507. },
  508. signers: [token],
  509. instructions: [
  510. anchor.web3.SystemProgram.transfer({
  511. fromPubkey: program.provider.wallet.publicKey,
  512. toPubkey: token.publicKey,
  513. lamports: 1,
  514. }),
  515. ],
  516. });
  517. const client = new Token(
  518. program.provider.connection,
  519. mint.publicKey,
  520. TOKEN_PROGRAM_ID,
  521. program.provider.wallet.payer
  522. );
  523. const account = await client.getAccountInfo(token.publicKey);
  524. assert.ok(account.state === 1);
  525. assert.ok(account.amount.toNumber() === 0);
  526. assert.ok(account.isInitialized);
  527. assert.ok(account.owner.equals(program.provider.wallet.publicKey));
  528. assert.ok(account.mint.equals(mint.publicKey));
  529. });
  530. });