misc.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. const anchor = require("@project-serum/anchor");
  2. const PublicKey = anchor.web3.PublicKey;
  3. const serumCmn = require("@project-serum/common");
  4. const assert = require("assert");
  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 init an associated program account", async () => {
  126. const state = await program.state.address();
  127. // Manual associated address calculation for test only. Clients should use
  128. // the generated methods.
  129. const [
  130. associatedAccount,
  131. nonce,
  132. ] = await anchor.web3.PublicKey.findProgramAddress(
  133. [
  134. Buffer.from([97, 110, 99, 104, 111, 114]), // b"anchor".
  135. program.provider.wallet.publicKey.toBuffer(),
  136. state.toBuffer(),
  137. data.publicKey.toBuffer(),
  138. ],
  139. program.programId
  140. );
  141. await assert.rejects(
  142. async () => {
  143. await program.account.testData.fetch(associatedAccount);
  144. },
  145. (err) => {
  146. assert.ok(
  147. err.toString() ===
  148. `Error: Account does not exist ${associatedAccount.toString()}`
  149. );
  150. return true;
  151. }
  152. );
  153. await program.rpc.testInitAssociatedAccount(new anchor.BN(1234), {
  154. accounts: {
  155. myAccount: associatedAccount,
  156. authority: program.provider.wallet.publicKey,
  157. state,
  158. data: data.publicKey,
  159. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  160. systemProgram: anchor.web3.SystemProgram.programId,
  161. },
  162. });
  163. // Try out the generated associated method.
  164. const account = await program.account.testData.associated(
  165. program.provider.wallet.publicKey,
  166. state,
  167. data.publicKey
  168. );
  169. assert.ok(account.data.toNumber() === 1234);
  170. });
  171. it("Can use an associated program account", async () => {
  172. const state = await program.state.address();
  173. const [
  174. associatedAccount,
  175. nonce,
  176. ] = await anchor.web3.PublicKey.findProgramAddress(
  177. [
  178. Buffer.from([97, 110, 99, 104, 111, 114]), // b"anchor".
  179. program.provider.wallet.publicKey.toBuffer(),
  180. state.toBuffer(),
  181. data.publicKey.toBuffer(),
  182. ],
  183. program.programId
  184. );
  185. await program.rpc.testAssociatedAccount(new anchor.BN(5), {
  186. accounts: {
  187. myAccount: associatedAccount,
  188. authority: program.provider.wallet.publicKey,
  189. state,
  190. data: data.publicKey,
  191. },
  192. });
  193. // Try out the generated associated method.
  194. const account = await program.account.testData.associated(
  195. program.provider.wallet.publicKey,
  196. state,
  197. data.publicKey
  198. );
  199. assert.ok(account.data.toNumber() === 5);
  200. });
  201. it("Can retrieve events when simulating a transaction", async () => {
  202. const resp = await program.simulate.testSimulate(44);
  203. const expectedRaw = [
  204. "Program Z2Ddx1Lcd8CHTV9tkWtNnFQrSz6kxz2H38wrr18zZRZ invoke [1]",
  205. "Program log: NgyCA9omwbMsAAAA",
  206. "Program log: fPhuIELK/k7SBAAA",
  207. "Program log: jvbowsvlmkcJAAAA",
  208. "Program Z2Ddx1Lcd8CHTV9tkWtNnFQrSz6kxz2H38wrr18zZRZ consumed 4819 of 200000 compute units",
  209. "Program Z2Ddx1Lcd8CHTV9tkWtNnFQrSz6kxz2H38wrr18zZRZ success",
  210. ];
  211. assert.ok(JSON.stringify(expectedRaw), resp.raw);
  212. assert.ok(resp.events[0].name === "E1");
  213. assert.ok(resp.events[0].data.data === 44);
  214. assert.ok(resp.events[1].name === "E2");
  215. assert.ok(resp.events[1].data.data === 1234);
  216. assert.ok(resp.events[2].name === "E3");
  217. assert.ok(resp.events[2].data.data === 9);
  218. });
  219. it("Can use i8 in the idl", async () => {
  220. const data = anchor.web3.Keypair.generate();
  221. await program.rpc.testI8(-3, {
  222. accounts: {
  223. data: data.publicKey,
  224. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  225. },
  226. instructions: [await program.account.dataI8.createInstruction(data)],
  227. signers: [data],
  228. });
  229. const dataAccount = await program.account.dataI8.fetch(data.publicKey);
  230. assert.ok(dataAccount.data === -3);
  231. });
  232. let dataPubkey;
  233. it("Can use i16 in the idl", async () => {
  234. const data = anchor.web3.Keypair.generate();
  235. await program.rpc.testI16(-2048, {
  236. accounts: {
  237. data: data.publicKey,
  238. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  239. },
  240. instructions: [await program.account.dataI16.createInstruction(data)],
  241. signers: [data],
  242. });
  243. const dataAccount = await program.account.dataI16.fetch(data.publicKey);
  244. assert.ok(dataAccount.data === -2048);
  245. dataPubkey = data.publicKey;
  246. });
  247. it("Can use base58 strings to fetch an account", async () => {
  248. const dataAccount = await program.account.dataI16.fetch(
  249. dataPubkey.toString()
  250. );
  251. assert.ok(dataAccount.data === -2048);
  252. });
  253. it("Should fail to close an account when sending lamports to itself", async () => {
  254. try {
  255. await program.rpc.testClose({
  256. accounts: {
  257. data: data.publicKey,
  258. solDest: data.publicKey,
  259. },
  260. });
  261. assert.ok(false);
  262. } catch (err) {
  263. const errMsg = "A close constraint was violated";
  264. assert.equal(err.toString(), errMsg);
  265. assert.equal(err.msg, errMsg);
  266. assert.equal(err.code, 151);
  267. }
  268. });
  269. it("Can close an account", async () => {
  270. const openAccount = await program.provider.connection.getAccountInfo(
  271. data.publicKey
  272. );
  273. assert.ok(openAccount !== null);
  274. let beforeBalance = (
  275. await program.provider.connection.getAccountInfo(
  276. program.provider.wallet.publicKey
  277. )
  278. ).lamports;
  279. await program.rpc.testClose({
  280. accounts: {
  281. data: data.publicKey,
  282. solDest: program.provider.wallet.publicKey,
  283. },
  284. });
  285. let afterBalance = (
  286. await program.provider.connection.getAccountInfo(
  287. program.provider.wallet.publicKey
  288. )
  289. ).lamports;
  290. // Retrieved rent exemption sol.
  291. assert.ok(afterBalance > beforeBalance);
  292. const closedAccount = await program.provider.connection.getAccountInfo(
  293. data.publicKey
  294. );
  295. assert.ok(closedAccount === null);
  296. });
  297. it("Can use instruction data in accounts constraints", async () => {
  298. // b"my-seed"
  299. const seed = Buffer.from([109, 121, 45, 115, 101, 101, 100]);
  300. const [myPda, nonce] = await PublicKey.findProgramAddress(
  301. [seed, anchor.web3.SYSVAR_RENT_PUBKEY.toBuffer()],
  302. program.programId
  303. );
  304. await program.rpc.testInstructionConstraint(nonce, {
  305. accounts: {
  306. myPda,
  307. myAccount: anchor.web3.SYSVAR_RENT_PUBKEY,
  308. },
  309. });
  310. });
  311. it("Can create a PDA account with instruction data", async () => {
  312. const seed = Buffer.from([1, 2, 3, 4]);
  313. const domain = "my-domain";
  314. const foo = anchor.web3.SYSVAR_RENT_PUBKEY;
  315. const [myPda, nonce] = await PublicKey.findProgramAddress(
  316. [
  317. Buffer.from(anchor.utils.bytes.utf8.encode("my-seed")),
  318. Buffer.from(anchor.utils.bytes.utf8.encode(domain)),
  319. foo.toBuffer(),
  320. seed,
  321. ],
  322. program.programId
  323. );
  324. await program.rpc.testPdaInit(domain, seed, nonce, {
  325. accounts: {
  326. myPda,
  327. myPayer: program.provider.wallet.publicKey,
  328. foo,
  329. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  330. systemProgram: anchor.web3.SystemProgram.programId,
  331. },
  332. });
  333. const myPdaAccount = await program.account.dataU16.fetch(myPda);
  334. assert.ok(myPdaAccount.data === 6);
  335. });
  336. it("Can create a zero copy PDA account", async () => {
  337. const [myPda, nonce] = await PublicKey.findProgramAddress(
  338. [Buffer.from(anchor.utils.bytes.utf8.encode("my-seed"))],
  339. program.programId
  340. );
  341. await program.rpc.testPdaInitZeroCopy(nonce, {
  342. accounts: {
  343. myPda,
  344. myPayer: program.provider.wallet.publicKey,
  345. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  346. systemProgram: anchor.web3.SystemProgram.programId,
  347. },
  348. });
  349. const myPdaAccount = await program.account.dataZeroCopy.fetch(myPda);
  350. assert.ok(myPdaAccount.data === 9);
  351. assert.ok((myPdaAccount.bump = nonce));
  352. });
  353. it("Can write to a zero copy PDA account", async () => {
  354. const [myPda, bump] = await PublicKey.findProgramAddress(
  355. [Buffer.from(anchor.utils.bytes.utf8.encode("my-seed"))],
  356. program.programId
  357. );
  358. await program.rpc.testPdaMutZeroCopy({
  359. accounts: {
  360. myPda,
  361. myPayer: program.provider.wallet.publicKey,
  362. },
  363. });
  364. const myPdaAccount = await program.account.dataZeroCopy.fetch(myPda);
  365. assert.ok(myPdaAccount.data === 1234);
  366. assert.ok((myPdaAccount.bump = bump));
  367. });
  368. });