misc.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  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. const { TOKEN_PROGRAM_ID, Token } = require("@solana/spl-token");
  6. describe("misc", () => {
  7. // Configure the client to use the local cluster.
  8. anchor.setProvider(anchor.Provider.env());
  9. const program = anchor.workspace.Misc;
  10. const misc2Program = anchor.workspace.Misc2;
  11. it("Can allocate extra space for a state constructor", async () => {
  12. const tx = await program.state.rpc.new();
  13. const addr = await program.state.address();
  14. const state = await program.state.fetch();
  15. const accountInfo = await program.provider.connection.getAccountInfo(addr);
  16. assert.ok(state.v.equals(Buffer.from([])));
  17. assert.ok(accountInfo.data.length === 99);
  18. });
  19. it("Can use remaining accounts for a state instruction", async () => {
  20. await program.state.rpc.remainingAccounts({
  21. remainingAccounts: [
  22. { pubkey: misc2Program.programId, isWritable: false, isSigner: false },
  23. ],
  24. });
  25. });
  26. const data = anchor.web3.Keypair.generate();
  27. it("Can use u128 and i128", async () => {
  28. const tx = await program.rpc.initialize(
  29. new anchor.BN(1234),
  30. new anchor.BN(22),
  31. {
  32. accounts: {
  33. data: data.publicKey,
  34. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  35. },
  36. signers: [data],
  37. instructions: [await program.account.data.createInstruction(data)],
  38. }
  39. );
  40. const dataAccount = await program.account.data.fetch(data.publicKey);
  41. assert.ok(dataAccount.udata.eq(new anchor.BN(1234)));
  42. assert.ok(dataAccount.idata.eq(new anchor.BN(22)));
  43. });
  44. it("Can use u16", async () => {
  45. const data = anchor.web3.Keypair.generate();
  46. const tx = await program.rpc.testU16(99, {
  47. accounts: {
  48. myAccount: data.publicKey,
  49. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  50. },
  51. signers: [data],
  52. instructions: [await program.account.dataU16.createInstruction(data)],
  53. });
  54. const dataAccount = await program.account.dataU16.fetch(data.publicKey);
  55. assert.ok(dataAccount.data === 99);
  56. });
  57. it("Can embed programs into genesis from the Anchor.toml", async () => {
  58. const pid = new anchor.web3.PublicKey(
  59. "FtMNMKp9DZHKWUyVAsj3Q5QV8ow4P3fUPP7ZrWEQJzKr"
  60. );
  61. let accInfo = await anchor.getProvider().connection.getAccountInfo(pid);
  62. assert.ok(accInfo.executable);
  63. });
  64. it("Can use the owner constraint", async () => {
  65. await program.rpc.testOwner({
  66. accounts: {
  67. data: data.publicKey,
  68. misc: program.programId,
  69. },
  70. });
  71. await assert.rejects(
  72. async () => {
  73. await program.rpc.testOwner({
  74. accounts: {
  75. data: program.provider.wallet.publicKey,
  76. misc: program.programId,
  77. },
  78. });
  79. },
  80. (err) => {
  81. return true;
  82. }
  83. );
  84. });
  85. it("Can use the executable attribute", async () => {
  86. await program.rpc.testExecutable({
  87. accounts: {
  88. program: program.programId,
  89. },
  90. });
  91. await assert.rejects(
  92. async () => {
  93. await program.rpc.testExecutable({
  94. accounts: {
  95. program: program.provider.wallet.publicKey,
  96. },
  97. });
  98. },
  99. (err) => {
  100. return true;
  101. }
  102. );
  103. });
  104. it("Can CPI to state instructions", async () => {
  105. const oldData = new anchor.BN(0);
  106. await misc2Program.state.rpc.new({
  107. accounts: {
  108. authority: program.provider.wallet.publicKey,
  109. },
  110. });
  111. let stateAccount = await misc2Program.state.fetch();
  112. assert.ok(stateAccount.data.eq(oldData));
  113. assert.ok(stateAccount.auth.equals(program.provider.wallet.publicKey));
  114. const newData = new anchor.BN(2134);
  115. await program.rpc.testStateCpi(newData, {
  116. accounts: {
  117. authority: program.provider.wallet.publicKey,
  118. cpiState: await misc2Program.state.address(),
  119. misc2Program: misc2Program.programId,
  120. },
  121. });
  122. stateAccount = await misc2Program.state.fetch();
  123. assert.ok(stateAccount.data.eq(newData));
  124. assert.ok(stateAccount.auth.equals(program.provider.wallet.publicKey));
  125. });
  126. it("Can init an associated program account", async () => {
  127. const state = await program.state.address();
  128. // Manual associated address calculation for test only. Clients should use
  129. // the generated methods.
  130. const [associatedAccount, nonce] =
  131. await anchor.web3.PublicKey.findProgramAddress(
  132. [
  133. anchor.utils.bytes.utf8.encode("anchor"),
  134. program.provider.wallet.publicKey.toBuffer(),
  135. state.toBuffer(),
  136. data.publicKey.toBuffer(),
  137. anchor.utils.bytes.utf8.encode("my-seed"),
  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. anchor.utils.bytes.utf8.encode("my-seed")
  169. );
  170. assert.ok(account.data.toNumber() === 1234);
  171. });
  172. it("Can use an associated program account", async () => {
  173. const state = await program.state.address();
  174. const [associatedAccount, nonce] =
  175. await anchor.web3.PublicKey.findProgramAddress(
  176. [
  177. anchor.utils.bytes.utf8.encode("anchor"),
  178. program.provider.wallet.publicKey.toBuffer(),
  179. state.toBuffer(),
  180. data.publicKey.toBuffer(),
  181. anchor.utils.bytes.utf8.encode("my-seed"),
  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. anchor.utils.bytes.utf8.encode("my-seed")
  199. );
  200. assert.ok(account.data.toNumber() === 5);
  201. });
  202. it("Can retrieve events when simulating a transaction", async () => {
  203. const resp = await program.simulate.testSimulate(44);
  204. const expectedRaw = [
  205. "Program Z2Ddx1Lcd8CHTV9tkWtNnFQrSz6kxz2H38wrr18zZRZ invoke [1]",
  206. "Program log: NgyCA9omwbMsAAAA",
  207. "Program log: fPhuIELK/k7SBAAA",
  208. "Program log: jvbowsvlmkcJAAAA",
  209. "Program Z2Ddx1Lcd8CHTV9tkWtNnFQrSz6kxz2H38wrr18zZRZ consumed 4819 of 200000 compute units",
  210. "Program Z2Ddx1Lcd8CHTV9tkWtNnFQrSz6kxz2H38wrr18zZRZ success",
  211. ];
  212. assert.ok(JSON.stringify(expectedRaw), resp.raw);
  213. assert.ok(resp.events[0].name === "E1");
  214. assert.ok(resp.events[0].data.data === 44);
  215. assert.ok(resp.events[1].name === "E2");
  216. assert.ok(resp.events[1].data.data === 1234);
  217. assert.ok(resp.events[2].name === "E3");
  218. assert.ok(resp.events[2].data.data === 9);
  219. });
  220. it("Can use i8 in the idl", async () => {
  221. const data = anchor.web3.Keypair.generate();
  222. await program.rpc.testI8(-3, {
  223. accounts: {
  224. data: data.publicKey,
  225. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  226. },
  227. instructions: [await program.account.dataI8.createInstruction(data)],
  228. signers: [data],
  229. });
  230. const dataAccount = await program.account.dataI8.fetch(data.publicKey);
  231. assert.ok(dataAccount.data === -3);
  232. });
  233. let dataPubkey;
  234. it("Can use i16 in the idl", async () => {
  235. const data = anchor.web3.Keypair.generate();
  236. await program.rpc.testI16(-2048, {
  237. accounts: {
  238. data: data.publicKey,
  239. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  240. },
  241. instructions: [await program.account.dataI16.createInstruction(data)],
  242. signers: [data],
  243. });
  244. const dataAccount = await program.account.dataI16.fetch(data.publicKey);
  245. assert.ok(dataAccount.data === -2048);
  246. dataPubkey = data.publicKey;
  247. });
  248. it("Can use base58 strings to fetch an account", async () => {
  249. const dataAccount = await program.account.dataI16.fetch(
  250. dataPubkey.toString()
  251. );
  252. assert.ok(dataAccount.data === -2048);
  253. });
  254. it("Should fail to close an account when sending lamports to itself", async () => {
  255. try {
  256. await program.rpc.testClose({
  257. accounts: {
  258. data: data.publicKey,
  259. solDest: data.publicKey,
  260. },
  261. });
  262. assert.ok(false);
  263. } catch (err) {
  264. const errMsg = "A close constraint was violated";
  265. assert.equal(err.toString(), errMsg);
  266. assert.equal(err.msg, errMsg);
  267. assert.equal(err.code, 151);
  268. }
  269. });
  270. it("Can close an account", async () => {
  271. const openAccount = await program.provider.connection.getAccountInfo(
  272. data.publicKey
  273. );
  274. assert.ok(openAccount !== null);
  275. let beforeBalance = (
  276. await program.provider.connection.getAccountInfo(
  277. program.provider.wallet.publicKey
  278. )
  279. ).lamports;
  280. await program.rpc.testClose({
  281. accounts: {
  282. data: data.publicKey,
  283. solDest: program.provider.wallet.publicKey,
  284. },
  285. });
  286. let afterBalance = (
  287. await program.provider.connection.getAccountInfo(
  288. program.provider.wallet.publicKey
  289. )
  290. ).lamports;
  291. // Retrieved rent exemption sol.
  292. assert.ok(afterBalance > beforeBalance);
  293. const closedAccount = await program.provider.connection.getAccountInfo(
  294. data.publicKey
  295. );
  296. assert.ok(closedAccount === null);
  297. });
  298. it("Can use instruction data in accounts constraints", async () => {
  299. // b"my-seed"
  300. const seed = Buffer.from([109, 121, 45, 115, 101, 101, 100]);
  301. const [myPda, nonce] = await PublicKey.findProgramAddress(
  302. [seed, anchor.web3.SYSVAR_RENT_PUBKEY.toBuffer()],
  303. program.programId
  304. );
  305. await program.rpc.testInstructionConstraint(nonce, {
  306. accounts: {
  307. myPda,
  308. myAccount: anchor.web3.SYSVAR_RENT_PUBKEY,
  309. },
  310. });
  311. });
  312. it("Can create a PDA account with instruction data", async () => {
  313. const seed = Buffer.from([1, 2, 3, 4]);
  314. const domain = "my-domain";
  315. const foo = anchor.web3.SYSVAR_RENT_PUBKEY;
  316. const [myPda, nonce] = await PublicKey.findProgramAddress(
  317. [
  318. Buffer.from(anchor.utils.bytes.utf8.encode("my-seed")),
  319. Buffer.from(anchor.utils.bytes.utf8.encode(domain)),
  320. foo.toBuffer(),
  321. seed,
  322. ],
  323. program.programId
  324. );
  325. await program.rpc.testPdaInit(domain, seed, nonce, {
  326. accounts: {
  327. myPda,
  328. myPayer: program.provider.wallet.publicKey,
  329. foo,
  330. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  331. systemProgram: anchor.web3.SystemProgram.programId,
  332. },
  333. });
  334. const myPdaAccount = await program.account.dataU16.fetch(myPda);
  335. assert.ok(myPdaAccount.data === 6);
  336. });
  337. it("Can create a zero copy PDA account", async () => {
  338. const [myPda, nonce] = await PublicKey.findProgramAddress(
  339. [Buffer.from(anchor.utils.bytes.utf8.encode("my-seed"))],
  340. program.programId
  341. );
  342. await program.rpc.testPdaInitZeroCopy(nonce, {
  343. accounts: {
  344. myPda,
  345. myPayer: program.provider.wallet.publicKey,
  346. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  347. systemProgram: anchor.web3.SystemProgram.programId,
  348. },
  349. });
  350. const myPdaAccount = await program.account.dataZeroCopy.fetch(myPda);
  351. assert.ok(myPdaAccount.data === 9);
  352. assert.ok((myPdaAccount.bump = nonce));
  353. });
  354. it("Can write to a zero copy PDA account", async () => {
  355. const [myPda, bump] = await PublicKey.findProgramAddress(
  356. [Buffer.from(anchor.utils.bytes.utf8.encode("my-seed"))],
  357. program.programId
  358. );
  359. await program.rpc.testPdaMutZeroCopy({
  360. accounts: {
  361. myPda,
  362. myPayer: program.provider.wallet.publicKey,
  363. },
  364. });
  365. const myPdaAccount = await program.account.dataZeroCopy.fetch(myPda);
  366. assert.ok(myPdaAccount.data === 1234);
  367. assert.ok((myPdaAccount.bump = bump));
  368. });
  369. it("Can create a token account from seeds pda", async () => {
  370. const mint = await Token.createMint(
  371. program.provider.connection,
  372. program.provider.wallet.payer,
  373. program.provider.wallet.publicKey,
  374. null,
  375. 0,
  376. TOKEN_PROGRAM_ID
  377. );
  378. const [myPda, bump] = await PublicKey.findProgramAddress(
  379. [Buffer.from(anchor.utils.bytes.utf8.encode("my-token-seed"))],
  380. program.programId
  381. );
  382. await program.rpc.testTokenSeedsInit(bump, {
  383. accounts: {
  384. myPda,
  385. mint: mint.publicKey,
  386. authority: program.provider.wallet.publicKey,
  387. systemProgram: anchor.web3.SystemProgram.programId,
  388. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  389. tokenProgram: TOKEN_PROGRAM_ID,
  390. },
  391. });
  392. const account = await mint.getAccountInfo(myPda);
  393. assert.ok(account.state === 1);
  394. assert.ok(account.amount.toNumber() === 0);
  395. assert.ok(account.isInitialized);
  396. assert.ok(account.owner.equals(program.provider.wallet.publicKey));
  397. assert.ok(account.mint.equals(mint.publicKey));
  398. });
  399. });