system-coder.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. import * as anchor from "@project-serum/anchor";
  2. import { Native } from "@project-serum/anchor";
  3. import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
  4. import {
  5. Keypair,
  6. LAMPORTS_PER_SOL,
  7. NONCE_ACCOUNT_LENGTH,
  8. PublicKey,
  9. SystemProgram,
  10. SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
  11. } from "@solana/web3.js";
  12. import * as assert from "assert";
  13. import BN from "bn.js";
  14. describe("system-coder", () => {
  15. // Configure the client to use the local cluster.
  16. const provider = anchor.AnchorProvider.env();
  17. anchor.setProvider(provider);
  18. // Client.
  19. const program = Native.system();
  20. // Constants.
  21. const aliceKeypair = Keypair.generate();
  22. it("Creates an account", async () => {
  23. // arrange
  24. const space = 100;
  25. const lamports =
  26. await program.provider.connection.getMinimumBalanceForRentExemption(
  27. space
  28. );
  29. const owner = SystemProgram.programId;
  30. // act
  31. await program.methods
  32. .createAccount(new BN(lamports), new BN(space), owner)
  33. .accounts({
  34. from: provider.wallet.publicKey,
  35. to: aliceKeypair.publicKey,
  36. })
  37. .signers([aliceKeypair])
  38. .rpc();
  39. // assert
  40. const aliceAccount = await program.provider.connection.getAccountInfo(
  41. aliceKeypair.publicKey
  42. );
  43. assert.notEqual(aliceAccount, null);
  44. assert.ok(owner.equals(aliceAccount.owner));
  45. assert.equal(lamports, aliceAccount.lamports);
  46. });
  47. it("Assigns an account to a program", async () => {
  48. // arrange
  49. const owner = TOKEN_PROGRAM_ID;
  50. // act
  51. await program.methods
  52. .assign(owner)
  53. .accounts({
  54. pubkey: aliceKeypair.publicKey,
  55. })
  56. .signers([aliceKeypair])
  57. .rpc();
  58. // assert
  59. const aliceAccount = await program.provider.connection.getAccountInfo(
  60. aliceKeypair.publicKey
  61. );
  62. assert.notEqual(aliceAccount, null);
  63. assert.ok(owner.equals(aliceAccount.owner));
  64. });
  65. it("Allocates space to an account", async () => {
  66. // arrange
  67. const newKeypair = Keypair.generate();
  68. const space = 100;
  69. const lamports =
  70. await program.provider.connection.getMinimumBalanceForRentExemption(
  71. space
  72. );
  73. // act
  74. await program.methods
  75. .allocate(new BN(space))
  76. .accounts({
  77. pubkey: newKeypair.publicKey,
  78. })
  79. .postInstructions([
  80. await program.methods
  81. .transfer(new BN(lamports))
  82. .accounts({
  83. from: provider.wallet.publicKey,
  84. to: newKeypair.publicKey,
  85. })
  86. .instruction(),
  87. ])
  88. .signers([newKeypair])
  89. .rpc();
  90. // assert
  91. const newAccountAfter = await program.provider.connection.getAccountInfo(
  92. newKeypair.publicKey
  93. );
  94. assert.equal(space, newAccountAfter.data.byteLength);
  95. });
  96. it("Creates an account with seed", async () => {
  97. const space = 100;
  98. const lamports =
  99. await program.provider.connection.getMinimumBalanceForRentExemption(
  100. space
  101. );
  102. const owner = SystemProgram.programId;
  103. const seed = "seeds";
  104. const bobPublicKey = await PublicKey.createWithSeed(
  105. aliceKeypair.publicKey,
  106. seed,
  107. owner
  108. );
  109. // act
  110. await program.methods
  111. .createAccountWithSeed(
  112. aliceKeypair.publicKey,
  113. seed,
  114. new BN(lamports),
  115. new BN(space),
  116. owner
  117. )
  118. .accounts({
  119. base: aliceKeypair.publicKey,
  120. from: provider.wallet.publicKey,
  121. to: bobPublicKey,
  122. })
  123. .signers([aliceKeypair])
  124. .rpc();
  125. // assert
  126. const bobAccount = await program.provider.connection.getAccountInfo(
  127. bobPublicKey
  128. );
  129. assert.notEqual(bobAccount, null);
  130. });
  131. it("Allocates and assigns an account with seed", async () => {
  132. const owner = TOKEN_PROGRAM_ID;
  133. const seed = "seeds2";
  134. const space = 100;
  135. const lamports =
  136. await program.provider.connection.getMinimumBalanceForRentExemption(
  137. space
  138. );
  139. const bobPublicKey = await PublicKey.createWithSeed(
  140. aliceKeypair.publicKey,
  141. seed,
  142. owner
  143. );
  144. // act
  145. await program.methods
  146. .allocateWithSeed(aliceKeypair.publicKey, seed, new BN(space), owner)
  147. .accounts({
  148. base: aliceKeypair.publicKey,
  149. account: bobPublicKey,
  150. })
  151. .postInstructions([
  152. await program.methods
  153. .transfer(new BN(lamports))
  154. .accounts({
  155. from: provider.wallet.publicKey,
  156. to: bobPublicKey,
  157. })
  158. .instruction(),
  159. await program.methods
  160. .assignWithSeed(aliceKeypair.publicKey, seed, owner)
  161. .accounts({
  162. base: aliceKeypair.publicKey,
  163. account: bobPublicKey,
  164. })
  165. .instruction(),
  166. ])
  167. .signers([aliceKeypair])
  168. .rpc();
  169. // assert
  170. const bobAccount = await program.provider.connection.getAccountInfo(
  171. bobPublicKey
  172. );
  173. assert.notEqual(bobAccount, null);
  174. assert.ok(owner.equals(bobAccount.owner));
  175. });
  176. it("Transfers from account with seed", async () => {
  177. const lamports = 1 * LAMPORTS_PER_SOL;
  178. const owner = SystemProgram.programId;
  179. const seed = "seeds3";
  180. const bobPublicKey = await PublicKey.createWithSeed(
  181. aliceKeypair.publicKey,
  182. seed,
  183. owner
  184. );
  185. const aliceAccountBefore = await program.provider.connection.getAccountInfo(
  186. aliceKeypair.publicKey
  187. );
  188. // act
  189. await program.methods
  190. .transfer(new BN(lamports))
  191. .accounts({
  192. from: provider.wallet.publicKey,
  193. to: bobPublicKey,
  194. })
  195. .rpc();
  196. await program.methods
  197. .transferWithSeed(new BN(lamports), seed, owner)
  198. .accounts({
  199. from: bobPublicKey,
  200. base: aliceKeypair.publicKey,
  201. to: aliceKeypair.publicKey,
  202. })
  203. .signers([aliceKeypair])
  204. .rpc();
  205. // assert
  206. const aliceAccountAfter = await program.provider.connection.getAccountInfo(
  207. aliceKeypair.publicKey
  208. );
  209. assert.equal(
  210. aliceAccountBefore.lamports + lamports,
  211. aliceAccountAfter.lamports
  212. );
  213. });
  214. it("Transfers lamports", async () => {
  215. // arrange
  216. const receiverKeypair = Keypair.generate();
  217. const lamports = 0.1 * LAMPORTS_PER_SOL;
  218. // act
  219. await program.methods
  220. .transfer(new BN(lamports))
  221. .accounts({
  222. from: provider.wallet.publicKey,
  223. to: receiverKeypair.publicKey,
  224. })
  225. .rpc();
  226. // assert
  227. const receiverAccount = await program.provider.connection.getAccountInfo(
  228. receiverKeypair.publicKey
  229. );
  230. assert.notEqual(receiverAccount, null);
  231. assert.equal(lamports, receiverAccount.lamports);
  232. });
  233. it("Initializes nonce account", async () => {
  234. // arrange
  235. const nonceKeypair = Keypair.generate();
  236. const owner = SystemProgram.programId;
  237. const space = NONCE_ACCOUNT_LENGTH;
  238. const lamports =
  239. await provider.connection.getMinimumBalanceForRentExemption(space);
  240. // act
  241. await program.methods
  242. .initializeNonceAccount(provider.wallet.publicKey)
  243. .accounts({
  244. nonce: nonceKeypair.publicKey,
  245. recentBlockhashes: SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
  246. })
  247. .preInstructions([
  248. await program.methods
  249. .createAccount(new BN(lamports), new BN(space), owner)
  250. .accounts({
  251. from: provider.wallet.publicKey,
  252. to: nonceKeypair.publicKey,
  253. })
  254. .instruction(),
  255. ])
  256. .signers([nonceKeypair])
  257. .rpc();
  258. // assert
  259. const nonceAccount = await program.account.nonce.fetch(
  260. nonceKeypair.publicKey
  261. );
  262. assert.notEqual(nonceAccount, null);
  263. assert.ok(nonceAccount.authorizedPubkey.equals(provider.wallet.publicKey));
  264. });
  265. it("Advances a nonce account", async () => {
  266. // arrange
  267. const nonceKeypair = Keypair.generate();
  268. const owner = SystemProgram.programId;
  269. const space = NONCE_ACCOUNT_LENGTH;
  270. const lamports =
  271. await provider.connection.getMinimumBalanceForRentExemption(space);
  272. // act
  273. await program.methods
  274. .initializeNonceAccount(provider.wallet.publicKey)
  275. .accounts({
  276. nonce: nonceKeypair.publicKey,
  277. recentBlockhashes: SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
  278. })
  279. .preInstructions([
  280. await program.methods
  281. .createAccount(new BN(lamports), new BN(space), owner)
  282. .accounts({
  283. from: provider.wallet.publicKey,
  284. to: nonceKeypair.publicKey,
  285. })
  286. .instruction(),
  287. ])
  288. .signers([nonceKeypair])
  289. .rpc();
  290. // These have to be separate to make sure advance is in another slot.
  291. await program.methods
  292. .advanceNonceAccount(provider.wallet.publicKey)
  293. .accounts({
  294. nonce: nonceKeypair.publicKey,
  295. recentBlockhashes: SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
  296. })
  297. .rpc();
  298. // assert
  299. const nonceAccount = await program.account.nonce.fetch(
  300. nonceKeypair.publicKey
  301. );
  302. assert.notEqual(nonceAccount, null);
  303. });
  304. it("Authorizes a nonce account", async () => {
  305. // arrange
  306. const nonceKeypair = Keypair.generate();
  307. const owner = SystemProgram.programId;
  308. const space = NONCE_ACCOUNT_LENGTH;
  309. const lamports =
  310. await provider.connection.getMinimumBalanceForRentExemption(space);
  311. // act
  312. await program.methods
  313. .initializeNonceAccount(provider.wallet.publicKey)
  314. .accounts({
  315. nonce: nonceKeypair.publicKey,
  316. recentBlockhashes: SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
  317. })
  318. .preInstructions([
  319. await program.methods
  320. .createAccount(new BN(lamports), new BN(space), owner)
  321. .accounts({
  322. from: provider.wallet.publicKey,
  323. to: nonceKeypair.publicKey,
  324. })
  325. .instruction(),
  326. ])
  327. .signers([nonceKeypair])
  328. .rpc();
  329. await program.methods
  330. .authorizeNonceAccount(aliceKeypair.publicKey)
  331. .accounts({
  332. nonce: nonceKeypair.publicKey,
  333. authorized: provider.wallet.publicKey,
  334. })
  335. .rpc();
  336. // assert
  337. const nonceAccount = await program.account.nonce.fetch(
  338. nonceKeypair.publicKey
  339. );
  340. assert.notEqual(nonceAccount, null);
  341. assert.ok(nonceAccount.authorizedPubkey.equals(aliceKeypair.publicKey));
  342. });
  343. it("Withdraws from nonce account", async () => {
  344. // arrange
  345. const nonceKeypair = Keypair.generate();
  346. const owner = SystemProgram.programId;
  347. const space = NONCE_ACCOUNT_LENGTH;
  348. const lamports =
  349. await provider.connection.getMinimumBalanceForRentExemption(space);
  350. const amount = 0.1 * LAMPORTS_PER_SOL;
  351. const aliceBalanceBefore = (
  352. await program.provider.connection.getAccountInfo(aliceKeypair.publicKey)
  353. ).lamports;
  354. // act
  355. await program.methods
  356. .initializeNonceAccount(provider.wallet.publicKey)
  357. .accounts({
  358. nonce: nonceKeypair.publicKey,
  359. recentBlockhashes: SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
  360. })
  361. .preInstructions([
  362. await program.methods
  363. .createAccount(new BN(lamports), new BN(space), owner)
  364. .accounts({
  365. from: provider.wallet.publicKey,
  366. to: nonceKeypair.publicKey,
  367. })
  368. .instruction(),
  369. ])
  370. .signers([nonceKeypair])
  371. .rpc();
  372. await program.methods
  373. .advanceNonceAccount(provider.wallet.publicKey)
  374. .accounts({
  375. nonce: nonceKeypair.publicKey,
  376. recentBlockhashes: SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
  377. })
  378. .postInstructions([
  379. await program.methods
  380. .transfer(new BN(amount))
  381. .accounts({
  382. from: provider.wallet.publicKey,
  383. to: nonceKeypair.publicKey,
  384. })
  385. .instruction(),
  386. ])
  387. .rpc();
  388. await program.methods
  389. .authorizeNonceAccount(aliceKeypair.publicKey)
  390. .accounts({
  391. nonce: nonceKeypair.publicKey,
  392. authorized: provider.wallet.publicKey,
  393. })
  394. .rpc();
  395. await program.methods
  396. .withdrawNonceAccount(new BN(amount))
  397. .accounts({
  398. authorized: aliceKeypair.publicKey,
  399. nonce: nonceKeypair.publicKey,
  400. recentBlockhashes: SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
  401. to: aliceKeypair.publicKey,
  402. })
  403. .signers([aliceKeypair])
  404. .rpc();
  405. // assert
  406. const aliceBalanceAfter = (
  407. await program.provider.connection.getAccountInfo(aliceKeypair.publicKey)
  408. ).lamports;
  409. assert.equal(aliceBalanceAfter - aliceBalanceBefore, amount);
  410. });
  411. });