misc.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  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. });