Browse Source

Merge pull request #36 from ZYJLiu/main

Update Solang examples to version 0.3.1 and add a cnft example
Nick Frostbutter 2 years ago
parent
commit
79574af95a
100 changed files with 3820 additions and 1622 deletions
  1. 7 2
      basics/account-data/solang/solidity/account-data.sol
  2. 18 19
      basics/account-data/solang/tests/account-data.ts
  3. 10 10
      basics/account-data/solang/tsconfig.json
  4. 1 1
      basics/checking-accounts/solang/solidity/checking-accounts.sol
  5. 24 23
      basics/checking-accounts/solang/tests/checking-accounts.ts
  6. 9 9
      basics/checking-accounts/solang/tsconfig.json
  7. 1 1
      basics/counter/solang/solidity/counter.sol
  8. 1 1
      basics/counter/solang/tests/counter.ts
  9. 9 9
      basics/counter/solang/tsconfig.json
  10. 1 1
      basics/cross-program-invocation/solang/solidity/hand.sol
  11. 1 1
      basics/cross-program-invocation/solang/solidity/lever.sol
  12. 31 31
      basics/cross-program-invocation/solang/tests/test.ts
  13. 9 9
      basics/cross-program-invocation/solang/tsconfig.json
  14. 1 1
      basics/hello-solana/solang/solidity/hello-solana.sol
  15. 13 13
      basics/hello-solana/solang/tests/hello-solana.ts
  16. 9 9
      basics/hello-solana/solang/tsconfig.json
  17. 14 14
      basics/pda-rent-payer/solang/libraries/system_instruction.sol
  18. 4 6
      basics/pda-rent-payer/solang/solidity/pda-rent-payer.sol
  19. 26 26
      basics/pda-rent-payer/solang/tests/pda-rent-payer.ts
  20. 9 9
      basics/pda-rent-payer/solang/tsconfig.json
  21. 1 1
      basics/processing-instructions/solang/solidity/processing-instructions.sol
  22. 16 16
      basics/processing-instructions/solang/tests/processing-instructions.ts
  23. 9 9
      basics/processing-instructions/solang/tsconfig.json
  24. 5 4
      basics/program-derived-addresses/solang/solidity/program-derived-addresses.sol
  25. 21 21
      basics/program-derived-addresses/solang/tests/program-derived-addresses.ts
  26. 9 10
      basics/program-derived-addresses/solang/tsconfig.json
  27. 0 0
      basics/rent/solang/libraries/minimum_balance.sol
  28. 14 14
      basics/rent/solang/libraries/system_instruction.sol
  29. 4 4
      basics/rent/solang/solidity/rent.sol
  30. 19 19
      basics/rent/solang/tests/rent.ts
  31. 9 9
      basics/rent/solang/tsconfig.json
  32. 14 14
      basics/transfer-sol/solang/libraries/system_instruction.sol
  33. 3 3
      basics/transfer-sol/solang/solidity/transfer-sol.sol
  34. 37 37
      basics/transfer-sol/solang/tests/transfer-sol.ts
  35. 8 0
      compression/cnft-solang/.gitignore
  36. 8 0
      compression/cnft-solang/.prettierignore
  37. 30 0
      compression/cnft-solang/Anchor.toml
  38. 3 0
      compression/cnft-solang/app/.eslintrc.json
  39. 37 0
      compression/cnft-solang/app/.gitignore
  40. 38 0
      compression/cnft-solang/app/README.md
  41. 30 0
      compression/cnft-solang/app/components/Confirmed.tsx
  42. 108 0
      compression/cnft-solang/app/components/QrCodeCnftMint.tsx
  43. 13 0
      compression/cnft-solang/app/components/WalletMultiButton.tsx
  44. 38 0
      compression/cnft-solang/app/contexts/WalletContextProvider.tsx
  45. 175 0
      compression/cnft-solang/app/idl/compressed_nft.ts
  46. 6 0
      compression/cnft-solang/app/next.config.js
  47. 36 0
      compression/cnft-solang/app/package.json
  48. 13 0
      compression/cnft-solang/app/pages/_app.tsx
  49. 13 0
      compression/cnft-solang/app/pages/_document.tsx
  50. 145 0
      compression/cnft-solang/app/pages/api/mintCnft.ts
  51. 25 0
      compression/cnft-solang/app/pages/index.tsx
  52. BIN
      compression/cnft-solang/app/public/favicon.ico
  53. 1 0
      compression/cnft-solang/app/public/next.svg
  54. 1 0
      compression/cnft-solang/app/public/vercel.svg
  55. 229 0
      compression/cnft-solang/app/styles/Home.module.css
  56. 107 0
      compression/cnft-solang/app/styles/globals.css
  57. 23 0
      compression/cnft-solang/app/tsconfig.json
  58. 15 0
      compression/cnft-solang/app/utils/setup.ts
  59. 12 0
      compression/cnft-solang/app/utils/uri.ts
  60. 12 0
      compression/cnft-solang/migrations/deploy.ts
  61. 21 0
      compression/cnft-solang/package.json
  62. 144 0
      compression/cnft-solang/solidity/compressed-nft.sol
  63. 188 0
      compression/cnft-solang/tests/compressed-nft.ts
  64. 11 0
      compression/cnft-solang/tsconfig.json
  65. 12 0
      compression/cnft-solang/utils/uri.ts
  66. 1 1
      tokens/create-token/solang/libraries/mpl_metadata.sol
  67. 10 10
      tokens/create-token/solang/libraries/spl_token.sol
  68. 14 14
      tokens/create-token/solang/libraries/system_instruction.sol
  69. 2 1
      tokens/create-token/solang/package.json
  70. 4 4
      tokens/create-token/solang/solidity/create-token.sol
  71. 31 31
      tokens/create-token/solang/tests/create-token.ts
  72. 9 9
      tokens/create-token/solang/tsconfig.json
  73. 1 1
      tokens/nft-minter/solang/libraries/mpl_metadata.sol
  74. 10 10
      tokens/nft-minter/solang/libraries/spl_token.sol
  75. 300 0
      tokens/nft-minter/solang/libraries/system_instruction.sol
  76. 1 0
      tokens/nft-minter/solang/package.json
  77. 5 5
      tokens/nft-minter/solang/solidity/nft-minter.sol
  78. 0 300
      tokens/nft-minter/solang/solidity/system_instruction.sol
  79. 30 30
      tokens/nft-minter/solang/tests/nft-minter.ts
  80. 1 1
      tokens/pda-mint-authority/solang/libraries/mpl_metadata.sol
  81. 10 10
      tokens/pda-mint-authority/solang/libraries/spl_token.sol
  82. 300 0
      tokens/pda-mint-authority/solang/libraries/system_instruction.sol
  83. 1 0
      tokens/pda-mint-authority/solang/package.json
  84. 10 9
      tokens/pda-mint-authority/solang/solidity/pda-mint-authority.sol
  85. 0 300
      tokens/pda-mint-authority/solang/solidity/system_instruction.sol
  86. 31 30
      tokens/pda-mint-authority/solang/tests/pda-mint-authority.ts
  87. 9 9
      tokens/pda-mint-authority/solang/tsconfig.json
  88. 1 1
      tokens/spl-token-minter/solang/libraries/mpl_metadata.sol
  89. 10 10
      tokens/spl-token-minter/solang/libraries/spl_token.sol
  90. 300 0
      tokens/spl-token-minter/solang/libraries/system_instruction.sol
  91. 1 0
      tokens/spl-token-minter/solang/package.json
  92. 6 6
      tokens/spl-token-minter/solang/solidity/spl-token-minter.sol
  93. 0 300
      tokens/spl-token-minter/solang/solidity/system_instruction.sol
  94. 30 31
      tokens/spl-token-minter/solang/tests/spl-token-minter.ts
  95. 9 9
      tokens/spl-token-minter/solang/tsconfig.json
  96. 134 0
      tokens/transfer-tokens/solang/libraries/mpl_metadata.sol
  97. 387 0
      tokens/transfer-tokens/solang/libraries/spl_token.sol
  98. 300 0
      tokens/transfer-tokens/solang/libraries/system_instruction.sol
  99. 1 0
      tokens/transfer-tokens/solang/package.json
  100. 0 134
      tokens/transfer-tokens/solang/solidity/mpl_metadata.sol

+ 7 - 2
basics/account-data/solang/solidity/account-data.sol

@@ -14,8 +14,13 @@ contract account_data {
     }
 
     @payer(payer) // "payer" is the account that pays to create the dataAccount
-    @space(space) // "space" allocated to the account (maximum 10240 bytes, maximum space that can be reallocate when creating account in program via a CPI)
-    constructor(address payer, uint16 space, string _name, uint8 _houseNumber, string _street, string _city) {
+    constructor(
+        @space uint16 space, // "space" allocated to the account (maximum 10240 bytes, maximum space that can be reallocate when creating account in program via a CPI) 
+        string _name, 
+        uint8 _houseNumber, 
+        string _street, 
+        string _city
+    ) {
         // The AddressInfo instance is initialized with the data passed to the constructor
         addressInfo = AddressInfo(_name, _houseNumber, _street, _city);
     }

+ 18 - 19
basics/account-data/solang/tests/account-data.ts

@@ -1,16 +1,16 @@
-import * as anchor from "@coral-xyz/anchor"
-import { Program } from "@coral-xyz/anchor"
-import { AccountData } from "../target/types/account_data"
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { AccountData } from "../target/types/account_data";
 
 describe("account-data", () => {
   // Configure the client to use the local cluster.
-  const provider = anchor.AnchorProvider.env()
-  anchor.setProvider(provider)
+  const provider = anchor.AnchorProvider.env();
+  anchor.setProvider(provider);
 
   // Generate a new random keypair for the data account.
-  const dataAccount = anchor.web3.Keypair.generate()
-  const wallet = provider.wallet
-  const program = anchor.workspace.AccountData as Program<AccountData>
+  const dataAccount = anchor.web3.Keypair.generate();
+  const wallet = provider.wallet;
+  const program = anchor.workspace.AccountData as Program<AccountData>;
 
   // Create the new account
   // Using 10240 bytes of space, because its unclear how to correctly calculate the minimum space needed for the account
@@ -18,7 +18,6 @@ describe("account-data", () => {
   it("Is initialized!", async () => {
     const tx = await program.methods
       .new(
-        wallet.publicKey, // payer
         10240, // space (10240 bytes is the maximum space allowed when allocating space through a program)
         "Joe C", // name
         136, // house number
@@ -27,18 +26,18 @@ describe("account-data", () => {
       )
       .accounts({ dataAccount: dataAccount.publicKey })
       .signers([dataAccount])
-      .rpc()
-    console.log("Your transaction signature", tx)
-  })
+      .rpc();
+    console.log("Your transaction signature", tx);
+  });
 
   // Get the account data
   it("Get AddressInfo Data", async () => {
     const val = await program.methods
       .get()
       .accounts({ dataAccount: dataAccount.publicKey })
-      .view()
-    console.log("State:", val)
-  })
+      .view();
+    console.log("State:", val);
+  });
 
   // Get the account data size
   // Testing how much space is used to store the account data
@@ -47,7 +46,7 @@ describe("account-data", () => {
     const size = await program.methods
       .getAddressInfoSize()
       .accounts({ dataAccount: dataAccount.publicKey })
-      .view()
-    console.log("Size:", size.toNumber())
-  })
-})
+      .view();
+    console.log("Size:", size.toNumber());
+  });
+});

+ 10 - 10
basics/account-data/solang/tsconfig.json

@@ -1,11 +1,11 @@
 {
-            "compilerOptions": {
-              "types": ["mocha", "chai"],
-              "typeRoots": ["./node_modules/@types"],
-              "lib": ["es2015"],
-              "module": "commonjs",
-              "target": "es6",
-              "esModuleInterop": true
-            }
-          }
-          
+  "compilerOptions": {
+    "types": ["mocha", "chai"],
+    "typeRoots": ["./node_modules/@types"],
+    "lib": ["es2015"],
+    "module": "commonjs",
+    "target": "es6",
+    "esModuleInterop": true
+  }
+}
+            

+ 1 - 1
basics/checking-accounts/solang/solidity/checking-accounts.sol

@@ -6,7 +6,7 @@ contract checking_accounts {
 
     // The dataAccount is unused in this example, but is a required account when using Solang
     @payer(payer) // "payer" is the account that pays to create the dataAccount
-    constructor(address payer) {}
+    constructor() {}
 
     function checkAccounts(address accountToChange, address accountToCreate) public view {
         print("Number of Accounts Provided: {:}".format(tx.accounts.length));

+ 24 - 23
basics/checking-accounts/solang/tests/checking-accounts.ts

@@ -1,38 +1,39 @@
-import * as anchor from "@coral-xyz/anchor"
-import { Program } from "@coral-xyz/anchor"
-import { CheckingAccounts } from "../target/types/checking_accounts"
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { CheckingAccounts } from "../target/types/checking_accounts";
 import {
   SystemProgram,
   Transaction,
   sendAndConfirmTransaction,
-} from "@solana/web3.js"
+} from "@solana/web3.js";
 
 describe("checking-accounts", () => {
   // Configure the client to use the local cluster.
-  const provider = anchor.AnchorProvider.env()
-  anchor.setProvider(provider)
+  const provider = anchor.AnchorProvider.env();
+  anchor.setProvider(provider);
 
   // Generate a new random keypair for the data account.
-  const dataAccount = anchor.web3.Keypair.generate()
+  const dataAccount = anchor.web3.Keypair.generate();
 
   // Generate a new keypair to represent the account we will change.
-  const accountToChange = anchor.web3.Keypair.generate()
+  const accountToChange = anchor.web3.Keypair.generate();
   // Generate a new keypair to represent the account we will create.
-  const accountToCreate = anchor.web3.Keypair.generate()
-  const wallet = provider.wallet as anchor.Wallet
-  const connection = provider.connection
+  const accountToCreate = anchor.web3.Keypair.generate();
+  const wallet = provider.wallet as anchor.Wallet;
+  const connection = provider.connection;
 
-  const program = anchor.workspace.CheckingAccounts as Program<CheckingAccounts>
+  const program = anchor.workspace
+    .CheckingAccounts as Program<CheckingAccounts>;
 
   it("Is initialized!", async () => {
     // Create the new dataAccount, this is an account required by Solang even though we don't use it
     const tx = await program.methods
-      .new(wallet.publicKey)
+      .new()
       .accounts({ dataAccount: dataAccount.publicKey })
       .signers([dataAccount])
-      .rpc({ skipPreflight: true })
-    console.log("Your transaction signature", tx)
-  })
+      .rpc({ skipPreflight: true });
+    console.log("Your transaction signature", tx);
+  });
 
   it("Create an account owned by our program", async () => {
     // Create the new account owned by our program by directly calling the system program
@@ -42,13 +43,13 @@ describe("checking-accounts", () => {
       lamports: await connection.getMinimumBalanceForRentExemption(0),
       space: 0,
       programId: program.programId, // Our program
-    })
+    });
 
     await sendAndConfirmTransaction(connection, new Transaction().add(ix), [
       wallet.payer,
       accountToChange,
-    ])
-  })
+    ]);
+  });
 
   it("Check Accounts", async () => {
     // Invoke the checkAccounts instruction on our program, passing in the account we want to "check"
@@ -68,7 +69,7 @@ describe("checking-accounts", () => {
         },
       ])
       .signers([accountToCreate])
-      .rpc({ skipPreflight: true })
-    console.log("Your transaction signature", tx)
-  })
-})
+      .rpc({ skipPreflight: true });
+    console.log("Your transaction signature", tx);
+  });
+});

+ 9 - 9
basics/checking-accounts/solang/tsconfig.json

@@ -1,11 +1,11 @@
 {
-            "compilerOptions": {
-              "types": ["mocha", "chai"],
-              "typeRoots": ["./node_modules/@types"],
-              "lib": ["es2015"],
-              "module": "commonjs",
-              "target": "es6",
-              "esModuleInterop": true
-            }
-          }
+  "compilerOptions": {
+    "types": ["mocha", "chai"],
+    "typeRoots": ["./node_modules/@types"],
+    "lib": ["es2015"],
+    "module": "commonjs",
+    "target": "es6",
+    "esModuleInterop": true
+  }
+}
           

+ 1 - 1
basics/counter/solang/solidity/counter.sol

@@ -6,7 +6,7 @@ contract counter {
 
     // The constructor is used to create a new counter account
     @payer(payer)  // The "payer" pays for the counter account creation
-    constructor(address payer) {
+    constructor() {
         // Initialize the count to zero
         count = 0;
     }

+ 1 - 1
basics/counter/solang/tests/counter.ts

@@ -17,7 +17,7 @@ describe("counter", () => {
   it("Is initialized!", async () => {
     // Initialize new Counter account
     const tx = await program.methods
-      .new(wallet.publicKey) // wallet.publicKey is the payer for the new account
+      .new() // wallet.publicKey is the payer for the new account
       .accounts({ dataAccount: dataAccount.publicKey })
       .signers([dataAccount]) // dataAccount keypair is a required signer because we're using it to create a new account
       .rpc()

+ 9 - 9
basics/counter/solang/tsconfig.json

@@ -1,11 +1,11 @@
 {
-            "compilerOptions": {
-              "types": ["mocha", "chai"],
-              "typeRoots": ["./node_modules/@types"],
-              "lib": ["es2015"],
-              "module": "commonjs",
-              "target": "es6",
-              "esModuleInterop": true
-            }
-          }
+    "compilerOptions": {
+      "types": ["mocha", "chai"],
+      "typeRoots": ["./node_modules/@types"],
+      "lib": ["es2015"],
+      "module": "commonjs",
+      "target": "es6",
+      "esModuleInterop": true
+    }
+  }
           

+ 1 - 1
basics/cross-program-invocation/solang/solidity/hand.sol

@@ -13,7 +13,7 @@ contract hand {
     // Creating a data account is required by Solang, but the account is not used in this example.
     // We only interact with the lever program.
     @payer(payer) // payer for the data account
-    constructor(address payer) {}
+    constructor() {}
 
     // "Pull the lever" by calling the switchPower instruction on the lever program via a Cross Program Invocation.
     function pullLever(address dataAccount, string name) public {

+ 1 - 1
basics/cross-program-invocation/solang/solidity/lever.sol

@@ -5,7 +5,7 @@ contract lever {
     bool private isOn = true;
 
     @payer(payer) // payer for the data account
-    constructor(address payer) {}
+    constructor() {}
 
     // Switch the power on or off
     function switchPower(string name) public {

+ 31 - 31
basics/cross-program-invocation/solang/tests/test.ts

@@ -1,49 +1,49 @@
-import * as anchor from "@coral-xyz/anchor"
-import { Program } from "@coral-xyz/anchor"
-import { Lever } from "../target/types/lever"
-import { Hand } from "../target/types/hand"
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { Lever } from "../target/types/lever";
+import { Hand } from "../target/types/hand";
 
 describe("cross-program-invocation", () => {
   // Configure the client to use the local cluster.
-  const provider = anchor.AnchorProvider.env()
-  anchor.setProvider(provider)
+  const provider = anchor.AnchorProvider.env();
+  anchor.setProvider(provider);
 
   // Generate a new keypair for the data accounts for each program
-  const dataAccountLever = anchor.web3.Keypair.generate()
-  const dataAccountHand = anchor.web3.Keypair.generate()
-  const wallet = provider.wallet
+  const dataAccountLever = anchor.web3.Keypair.generate();
+  const dataAccountHand = anchor.web3.Keypair.generate();
+  const wallet = provider.wallet;
 
   // The lever program and hand program
-  const leverProgram = anchor.workspace.Lever as Program<Lever>
-  const handProgram = anchor.workspace.Hand as Program<Hand>
+  const leverProgram = anchor.workspace.Lever as Program<Lever>;
+  const handProgram = anchor.workspace.Hand as Program<Hand>;
 
   it("Initialize the lever!", async () => {
     // Initialize data account for the lever program
     const tx = await leverProgram.methods
-      .new(wallet.publicKey)
+      .new()
       .accounts({ dataAccount: dataAccountLever.publicKey })
       .signers([dataAccountLever])
-      .rpc()
-    console.log("Your transaction signature", tx)
+      .rpc();
+    console.log("Your transaction signature", tx);
 
     // Fetch the state of the data account
     const val = await leverProgram.methods
       .get()
       .accounts({ dataAccount: dataAccountLever.publicKey })
-      .view()
+      .view();
 
-    console.log("State:", val)
-  })
+    console.log("State:", val);
+  });
 
   it("Pull the lever!", async () => {
     // Initialize data account for the hand program
     // This is required by Solang, but the account is not used
     const tx = await handProgram.methods
-      .new(wallet.publicKey)
+      .new()
       .accounts({ dataAccount: dataAccountHand.publicKey })
       .signers([dataAccountHand])
-      .rpc()
-    console.log("Your transaction signature", tx)
+      .rpc();
+    console.log("Your transaction signature", tx);
 
     // Call the pullLever instruction on the hand program, which invokes the lever program via CPI
     const tx2 = await handProgram.methods
@@ -61,17 +61,17 @@ describe("cross-program-invocation", () => {
           isSigner: false,
         },
       ])
-      .rpc({ skipPreflight: true })
-    console.log("Your transaction signature", tx2)
+      .rpc({ skipPreflight: true });
+    console.log("Your transaction signature", tx2);
 
     // Fetch the state of the data account
     const val = await leverProgram.methods
       .get()
       .accounts({ dataAccount: dataAccountLever.publicKey })
-      .view()
+      .view();
 
-    console.log("State:", val)
-  })
+    console.log("State:", val);
+  });
 
   it("Pull it again!", async () => {
     // Call the pullLever instruction on the hand program, which invokes the lever program via CPI
@@ -90,16 +90,16 @@ describe("cross-program-invocation", () => {
           isSigner: false,
         },
       ])
-      .rpc({ skipPreflight: true })
+      .rpc({ skipPreflight: true });
 
-    console.log("Your transaction signature", tx)
+    console.log("Your transaction signature", tx);
 
     // Fetch the state of the data account
     const val = await leverProgram.methods
       .get()
       .accounts({ dataAccount: dataAccountLever.publicKey })
-      .view()
+      .view();
 
-    console.log("State:", val)
-  })
-})
+    console.log("State:", val);
+  });
+});

+ 9 - 9
basics/cross-program-invocation/solang/tsconfig.json

@@ -1,11 +1,11 @@
 {
-            "compilerOptions": {
-              "types": ["mocha", "chai"],
-              "typeRoots": ["./node_modules/@types"],
-              "lib": ["es2015"],
-              "module": "commonjs",
-              "target": "es6",
-              "esModuleInterop": true
-            }
-          }
+  "compilerOptions": {
+    "types": ["mocha", "chai"],
+    "typeRoots": ["./node_modules/@types"],
+    "lib": ["es2015"],
+    "module": "commonjs",
+    "target": "es6",
+    "esModuleInterop": true
+  }
+}
           

+ 1 - 1
basics/hello-solana/solang/solidity/hello-solana.sol

@@ -4,7 +4,7 @@ contract hello_solana {
     // The constructor is used to create a new account
     // Here we create a new account that stores no data and only prints messages to the program logs when the constructor is called.
     @payer(payer) // The "payer" pays for the account creation
-    constructor(address payer) {
+    constructor() {
         // We get the program ID by calling 'type(hello_solana).program_id', where "hello_solana" is the name of the contract.
         address programId = type(hello_solana).program_id;
 

+ 13 - 13
basics/hello-solana/solang/tests/hello-solana.ts

@@ -1,25 +1,25 @@
-import * as anchor from "@coral-xyz/anchor"
-import { Program } from "@coral-xyz/anchor"
-import { HelloSolana } from "../target/types/hello_solana"
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { HelloSolana } from "../target/types/hello_solana";
 
 describe("hello-solana", () => {
   // Configure the client to use the local cluster.
-  const provider = anchor.AnchorProvider.env()
-  anchor.setProvider(provider)
+  const provider = anchor.AnchorProvider.env();
+  anchor.setProvider(provider);
 
   // Generate a new random keypair for the data account.
-  const dataAccount = anchor.web3.Keypair.generate()
-  const wallet = provider.wallet
+  const dataAccount = anchor.web3.Keypair.generate();
+  const wallet = provider.wallet;
 
-  const program = anchor.workspace.HelloSolana as Program<HelloSolana>
+  const program = anchor.workspace.HelloSolana as Program<HelloSolana>;
 
   it("Is initialized!", async () => {
     // Initialize a new data account
     const tx = await program.methods
-      .new(wallet.publicKey) // wallet.publicKey is the payer for the new account
+      .new() // wallet.publicKey is the payer for the new account
       .accounts({ dataAccount: dataAccount.publicKey })
       .signers([dataAccount]) // dataAccount keypair is a required signer because we're using it to create a new account
-      .rpc()
-    console.log("Your transaction signature", tx)
-  })
-})
+      .rpc();
+    console.log("Your transaction signature", tx);
+  });
+});

+ 9 - 9
basics/hello-solana/solang/tsconfig.json

@@ -1,11 +1,11 @@
 {
-            "compilerOptions": {
-              "types": ["mocha", "chai"],
-              "typeRoots": ["./node_modules/@types"],
-              "lib": ["es2015"],
-              "module": "commonjs",
-              "target": "es6",
-              "esModuleInterop": true
-            }
-          }
+  "compilerOptions": {
+    "types": ["mocha", "chai"],
+    "typeRoots": ["./node_modules/@types"],
+    "lib": ["es2015"],
+    "module": "commonjs",
+    "target": "es6",
+    "esModuleInterop": true
+  }
+}
           

+ 14 - 14
basics/pda-rent-payer/solang/solidity/system_instruction.sol → basics/pda-rent-payer/solang/libraries/system_instruction.sol

@@ -34,7 +34,7 @@ library SystemInstruction {
     /// @param lamports amount of lamports to be transfered to the new account
     /// @param space the size in bytes that is going to be made available for the account
     /// @param owner public key for the program that will own the account being created
-    function create_account(address from, address to, uint64 lamports, uint64 space, address owner) internal view {
+    function create_account(address from, address to, uint64 lamports, uint64 space, address owner) internal {
         AccountMeta[2] metas = [
             AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
             AccountMeta({pubkey: to, is_signer: true, is_writable: true})
@@ -54,7 +54,7 @@ library SystemInstruction {
     /// @param lamports amount of lamports to be transfered to the new account
     /// @param space the size in bytes that is going to be made available for the account
     /// @param owner public key for the program that will own the account being created
-    function create_account_with_seed(address from, address to, address base, string seed, uint64 lamports, uint64 space, address owner) internal view {
+    function create_account_with_seed(address from, address to, address base, string seed, uint64 lamports, uint64 space, address owner) internal {
         AccountMeta[3] metas = [
             AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
             AccountMeta({pubkey: to, is_signer: false, is_writable: true}),
@@ -81,7 +81,7 @@ library SystemInstruction {
     ///
     /// @param pubkey the public key for the account whose owner is going to be reassigned
     /// @param owner the public key for the new account owner
-    function assign(address pubkey, address owner) internal view {
+    function assign(address pubkey, address owner) internal {
         AccountMeta[1] meta = [
             AccountMeta({pubkey: pubkey, is_signer: true, is_writable: true})
         ];
@@ -96,7 +96,7 @@ library SystemInstruction {
     /// @param base the base address that derived the 'addr' key using the seed
     /// @param seed the string utilized to created the 'addr' public key
     /// @param owner the public key for the new program owner
-    function assign_with_seed(address addr, address base, string seed, address owner) internal view {
+    function assign_with_seed(address addr, address base, string seed, address owner) internal {
         AccountMeta[2] metas = [
             AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: base, is_signer: true, is_writable: false})
@@ -119,7 +119,7 @@ library SystemInstruction {
     /// @param from public key for the funding account
     /// @param to public key for the recipient account
     /// @param lamports amount of lamports to transfer
-    function transfer(address from, address to, uint64 lamports) internal view {
+    function transfer(address from, address to, uint64 lamports) internal {
         AccountMeta[2] metas = [
             AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
             AccountMeta({pubkey: to, is_signer: false, is_writable: true})
@@ -138,7 +138,7 @@ library SystemInstruction {
     /// @param from_owner owner to use to derive the funding account address
     /// @param to_pubkey the public key for the recipient account
     /// @param lamports amount of lamports to transfer
-    function transfer_with_seed(address from_pubkey, address from_base, string seed, address from_owner, address to_pubkey, uint64 lamports) internal view {
+    function transfer_with_seed(address from_pubkey, address from_base, string seed, address from_owner, address to_pubkey, uint64 lamports) internal {
         AccountMeta[3] metas = [
             AccountMeta({pubkey: from_pubkey, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: from_base, is_signer: true, is_writable: false}),
@@ -160,7 +160,7 @@ library SystemInstruction {
     ///
     /// @param pub_key account for which to allocate space
     /// @param space number of bytes of memory to allocate
-    function allocate(address pub_key, uint64 space) internal view {
+    function allocate(address pub_key, uint64 space) internal {
         AccountMeta[1] meta = [
             AccountMeta({pubkey: pub_key, is_signer: true, is_writable: true})
         ];
@@ -177,7 +177,7 @@ library SystemInstruction {
     /// @param seed the string utilized to create the 'addr' public key
     /// @param space number of bytes of memory to allocate
     /// @param owner owner to use to derive the 'addr' account address
-    function allocate_with_seed(address addr, address base, string seed, uint64 space, address owner) internal view {
+    function allocate_with_seed(address addr, address base, string seed, uint64 space, address owner) internal {
         AccountMeta[2] metas = [
             AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: base, is_signer: true, is_writable: false})
@@ -204,7 +204,7 @@ library SystemInstruction {
     /// @param seed the string utilized to create the 'addr' public key
     /// @param authority The entity authorized to execute nonce instructions on the account
     /// @param lamports amount of lamports to be transfered to the new account
-    function create_nonce_account_with_seed(address from, address nonce, address base, string seed, address authority, uint64 lamports) internal view {
+    function create_nonce_account_with_seed(address from, address nonce, address base, string seed, address authority, uint64 lamports) internal {
         create_account_with_seed(from, nonce, base, seed, lamports, state_size, systemAddress);
 
         AccountMeta[3] metas = [
@@ -223,7 +223,7 @@ library SystemInstruction {
     /// @param nonce the public key for the nonce account to be created
     /// @param authority The entity authorized to execute nonce instructions on the account
     /// @param lamports amount of lamports to be transfered to the new account
-    function create_nonce_account(address from, address nonce, address authority, uint64 lamports) internal view {
+    function create_nonce_account(address from, address nonce, address authority, uint64 lamports) internal {
         create_account(from, nonce, lamports, state_size, systemAddress);
 
         AccountMeta[3] metas = [
@@ -240,7 +240,7 @@ library SystemInstruction {
     ///
     /// @param nonce_pubkey the public key for the nonce account
     /// @param authorized_pubkey the publick key for the entity authorized to execute instructins on the account
-    function advance_nonce_account(address nonce_pubkey, address authorized_pubkey) internal view {
+    function advance_nonce_account(address nonce_pubkey, address authorized_pubkey) internal {
         AccountMeta[3] metas = [
             AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
@@ -257,7 +257,7 @@ library SystemInstruction {
     /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
     /// @param to_pubkey the recipient account
     /// @param lamports the number of lamports to withdraw
-    function withdraw_nonce_account(address nonce_pubkey, address authorized_pubkey, address to_pubkey, uint64 lamports) internal view {
+    function withdraw_nonce_account(address nonce_pubkey, address authorized_pubkey, address to_pubkey, uint64 lamports) internal {
         AccountMeta[5] metas = [
             AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: to_pubkey, is_signer: false, is_writable: true}),
@@ -275,7 +275,7 @@ library SystemInstruction {
     /// @param nonce_pubkey the public key for the nonce account
     /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
     /// @param new_authority
-    function authorize_nonce_account(address nonce_pubkey, address authorized_pubkey, address new_authority) internal view {
+    function authorize_nonce_account(address nonce_pubkey, address authorized_pubkey, address new_authority) internal {
         AccountMeta[2] metas = [
             AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
@@ -289,7 +289,7 @@ library SystemInstruction {
     ///
     /// @param nonce the public key for the nonce account
     // This is not available on Solana v1.9.15
-    function upgrade_nonce_account(address nonce) internal view {
+    function upgrade_nonce_account(address nonce) internal {
         AccountMeta[1] meta = [
             AccountMeta({pubkey: nonce, is_signer: false, is_writable: true})
         ];

+ 4 - 6
basics/pda-rent-payer/solang/solidity/pda-rent-payer.sol

@@ -1,14 +1,12 @@
 
-import "./system_instruction.sol";
+import "../libraries/system_instruction.sol";
 
 @program_id("F1ipperKF9EfD821ZbbYjS319LXYiBmjhzkkf5a26rC")
 contract pda_rent_payer {
-    bool private value = true;
 
     @payer(payer) // "payer" is the account that pays for creating the account
     @seed("rent_vault") // hardcoded seed
-    @bump(bump) // bump seed to derive the pda
-    constructor(address payer, bytes1 bump, uint64 fundLamports) {
+    constructor(@bump bytes1 bump, uint64 fundLamports) {
         // Independently derive the PDA address from the seeds, bump, and programId
         (address pda, bytes1 _bump) = try_find_program_address(["rent_vault"], type(pda_rent_payer).program_id);
 
@@ -18,7 +16,7 @@ contract pda_rent_payer {
 
         // Fund the pda account with additional lamports
         SystemInstruction.transfer(
-            payer, // from
+            tx.accounts.payer.key, // from
             address(this), // to (the address of the account being created)
             fundLamports // amount of lamports to transfer
         );
@@ -30,7 +28,7 @@ contract pda_rent_payer {
 
         print("From: {:}".format(from.key));
         print("To: {:}".format(to.key));
-
+        
         from.lamports -= lamports;
         to.lamports += lamports;
     }

+ 26 - 26
basics/pda-rent-payer/solang/tests/pda-rent-payer.ts

@@ -1,45 +1,45 @@
-import * as anchor from "@coral-xyz/anchor"
-import { Program } from "@coral-xyz/anchor"
-import { PdaRentPayer } from "../target/types/pda_rent_payer"
-import { PublicKey } from "@solana/web3.js"
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { PdaRentPayer } from "../target/types/pda_rent_payer";
+import { PublicKey } from "@solana/web3.js";
 
 describe("pda-rent-payer", () => {
   // Configure the client to use the local cluster.
-  const provider = anchor.AnchorProvider.env()
-  anchor.setProvider(provider)
+  const provider = anchor.AnchorProvider.env();
+  anchor.setProvider(provider);
 
-  const wallet = provider.wallet
-  const connection = provider.connection
+  const wallet = provider.wallet;
+  const connection = provider.connection;
 
-  const program = anchor.workspace.PdaRentPayer as Program<PdaRentPayer>
+  const program = anchor.workspace.PdaRentPayer as Program<PdaRentPayer>;
 
   // Amount of additional lamports to fund the dataAccount with.
-  const fundLamports = 1 * anchor.web3.LAMPORTS_PER_SOL
+  const fundLamports = 1 * anchor.web3.LAMPORTS_PER_SOL;
 
   // Derive the PDA that will be used to initialize the dataAccount.
   const [dataAccountPDA, bump] = PublicKey.findProgramAddressSync(
     [Buffer.from("rent_vault")],
     program.programId
-  )
+  );
 
   it("Initialize the Rent Vault", async () => {
     // Add your test here.
     const tx = await program.methods
-      .new(wallet.publicKey, [bump], new anchor.BN(fundLamports))
+      .new([bump], new anchor.BN(fundLamports))
       .accounts({ dataAccount: dataAccountPDA })
-      .rpc()
-    console.log("Your transaction signature", tx)
+      .rpc();
+    console.log("Your transaction signature", tx);
 
-    const accountInfo = await connection.getAccountInfo(dataAccountPDA)
-    console.log("AccountInfo Lamports:", accountInfo.lamports)
-  })
+    const accountInfo = await connection.getAccountInfo(dataAccountPDA);
+    console.log("AccountInfo Lamports:", accountInfo.lamports);
+  });
 
   it("Create a new account using the Rent Vault", async () => {
-    const newAccount = anchor.web3.Keypair.generate()
-    const space = 100 // number of bytes
+    const newAccount = anchor.web3.Keypair.generate();
+    const space = 100; // number of bytes
 
     // Get the minimum balance for the account to be rent exempt.
-    const lamports = await connection.getMinimumBalanceForRentExemption(space)
+    const lamports = await connection.getMinimumBalanceForRentExemption(space);
 
     // Invoke the createNewAccount instruction on our program
     const tx = await program.methods
@@ -52,10 +52,10 @@ describe("pda-rent-payer", () => {
           isSigner: false,
         },
       ])
-      .rpc()
-    console.log("Your transaction signature", tx)
+      .rpc();
+    console.log("Your transaction signature", tx);
 
-    const accountInfo = await connection.getAccountInfo(newAccount.publicKey)
-    console.log("AccountInfo Lamports:", accountInfo.lamports)
-  })
-})
+    const accountInfo = await connection.getAccountInfo(newAccount.publicKey);
+    console.log("AccountInfo Lamports:", accountInfo.lamports);
+  });
+});

+ 9 - 9
basics/pda-rent-payer/solang/tsconfig.json

@@ -1,11 +1,11 @@
 {
-            "compilerOptions": {
-              "types": ["mocha", "chai"],
-              "typeRoots": ["./node_modules/@types"],
-              "lib": ["es2015"],
-              "module": "commonjs",
-              "target": "es6",
-              "esModuleInterop": true
-            }
-          }
+  "compilerOptions": {
+    "types": ["mocha", "chai"],
+    "typeRoots": ["./node_modules/@types"],
+    "lib": ["es2015"],
+    "module": "commonjs",
+    "target": "es6",
+    "esModuleInterop": true
+  }
+}
           

+ 1 - 1
basics/processing-instructions/solang/solidity/processing-instructions.sol

@@ -3,7 +3,7 @@
 contract processing_instructions {
 
     @payer(payer) // payer for the data account, required by Solang but not used in this example
-    constructor(address payer) {}
+    constructor() {}
 
     function goToPark(string name, uint32 height) public pure {
         // Print messages to the program logs

+ 16 - 16
basics/processing-instructions/solang/tests/processing-instructions.ts

@@ -1,40 +1,40 @@
-import * as anchor from "@coral-xyz/anchor"
-import { Program } from "@coral-xyz/anchor"
-import { ProcessingInstructions } from "../target/types/processing_instructions"
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { ProcessingInstructions } from "../target/types/processing_instructions";
 
 describe("processing-instructions", () => {
   // Configure the client to use the local cluster.
-  const provider = anchor.AnchorProvider.env()
-  anchor.setProvider(provider)
+  const provider = anchor.AnchorProvider.env();
+  anchor.setProvider(provider);
 
   // Generate a new keypair for the data account for the program
-  const dataAccount = anchor.web3.Keypair.generate()
-  const wallet = provider.wallet
+  const dataAccount = anchor.web3.Keypair.generate();
+  const wallet = provider.wallet;
 
   const program = anchor.workspace
-    .ProcessingInstructions as Program<ProcessingInstructions>
+    .ProcessingInstructions as Program<ProcessingInstructions>;
 
   it("Is initialized!", async () => {
     // Initialize data account for the program, which is required by Solang
     const tx = await program.methods
-      .new(wallet.publicKey)
+      .new()
       .accounts({ dataAccount: dataAccount.publicKey })
       .signers([dataAccount])
-      .rpc()
-    console.log("Your transaction signature", tx)
-  })
+      .rpc();
+    console.log("Your transaction signature", tx);
+  });
 
   it("Go to the park!", async () => {
     // Call the goToPark instruction on the program, providing the instruction data
     await program.methods
       .goToPark("Jimmy", 3)
       .accounts({ dataAccount: dataAccount.publicKey })
-      .rpc()
+      .rpc();
 
     // Call the goToPark instruction on the program, providing the instruction data
     await program.methods
       .goToPark("Mary", 10)
       .accounts({ dataAccount: dataAccount.publicKey })
-      .rpc()
-  })
-})
+      .rpc();
+  });
+});

+ 9 - 9
basics/processing-instructions/solang/tsconfig.json

@@ -1,11 +1,11 @@
 {
-            "compilerOptions": {
-              "types": ["mocha", "chai"],
-              "typeRoots": ["./node_modules/@types"],
-              "lib": ["es2015"],
-              "module": "commonjs",
-              "target": "es6",
-              "esModuleInterop": true
-            }
-          }
+  "compilerOptions": {
+    "types": ["mocha", "chai"],
+    "typeRoots": ["./node_modules/@types"],
+    "lib": ["es2015"],
+    "module": "commonjs",
+    "target": "es6",
+    "esModuleInterop": true
+  }
+}
           

+ 5 - 4
basics/program-derived-addresses/solang/solidity/program-derived-addresses.sol

@@ -17,11 +17,12 @@ contract program_derived_addresses {
     // The seeds, bump, and programId are used to derive a unique and deterministic pda (program derived address) to use as the account address
     @payer(payer) // "payer" is the account that pays for creating the account
     @seed("page_visits") // hardcoded seed
-    @seed(abi.encode(payer)) // additional seed using the payer address
-    @bump(bump) // bump seed to derive the pda
-    constructor(address payer, bytes1 bump) {
+    constructor(
+        @seed bytes payer, // additional seed using the payer address
+        @bump bytes1 bump // bump seed to derive the pda
+    ) {
         // Independently derive the PDA address from the seeds, bump, and programId
-        (address pda, bytes1 _bump) = try_find_program_address(["page_visits", abi.encode(payer)], type(program_derived_addresses).program_id);
+        (address pda, bytes1 _bump) = try_find_program_address(["page_visits", payer], type(program_derived_addresses).program_id);
 
         // Verify that the bump passed to the constructor matches the bump derived from the seeds and programId
         // This ensures that only the canonical pda address can be used to create the account (first bump that generates a valid pda address)

+ 21 - 21
basics/program-derived-addresses/solang/tests/program-derived-addresses.ts

@@ -1,23 +1,23 @@
-import * as anchor from "@coral-xyz/anchor"
-import { Program } from "@coral-xyz/anchor"
-import { ProgramDerivedAddresses } from "../target/types/program_derived_addresses"
-import { PublicKey } from "@solana/web3.js"
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { ProgramDerivedAddresses } from "../target/types/program_derived_addresses";
+import { PublicKey } from "@solana/web3.js";
 
 describe("program-derived-addresses", () => {
   // Configure the client to use the local cluster.
-  const provider = anchor.AnchorProvider.env()
-  anchor.setProvider(provider)
+  const provider = anchor.AnchorProvider.env();
+  anchor.setProvider(provider);
 
-  const wallet = provider.wallet
+  const wallet = provider.wallet;
 
   const program = anchor.workspace
-    .ProgramDerivedAddresses as Program<ProgramDerivedAddresses>
+    .ProgramDerivedAddresses as Program<ProgramDerivedAddresses>;
 
   // Derive the PDA that will be used to initialize the dataAccount.
   const [dataAccountPDA, bump] = PublicKey.findProgramAddressSync(
     [Buffer.from("page_visits"), wallet.publicKey.toBuffer()],
     program.programId
-  )
+  );
 
   it("Is initialized!", async () => {
     // Initialize the dataAccount using a PDA as the address.
@@ -25,36 +25,36 @@ describe("program-derived-addresses", () => {
     // This is a feature of PDAs that allows programs to "sign" for PDA that are derived from their programId.
     const tx = await program.methods
       .new(
-        wallet.publicKey, // wallet.publicKey is the payer for the new account
+        wallet.publicKey.toBuffer(), // wallet.publicKey is the payer for the new account
         [bump] // bump seed for the PDA found using findProgramAddress
       )
       .accounts({ dataAccount: dataAccountPDA })
-      .rpc({ skipPreflight: true })
-    console.log("Your transaction signature", tx)
+      .rpc({ skipPreflight: true });
+    console.log("Your transaction signature", tx);
 
     // Get the current state of the dataAccount.
     const val = await program.methods
       .get()
       .accounts({ dataAccount: dataAccountPDA })
-      .view()
+      .view();
 
-    console.log("State:", val)
-  })
+    console.log("State:", val);
+  });
 
   it("Visit the page!", async () => {
     // Increment the page visits counter.
     const tx = await program.methods
       .incrementPageVisits()
       .accounts({ dataAccount: dataAccountPDA })
-      .rpc()
-    console.log("Your transaction signature", tx)
+      .rpc();
+    console.log("Your transaction signature", tx);
 
     // Get the current state of the dataAccount.
     const val = await program.methods
       .get()
       .accounts({ dataAccount: dataAccountPDA })
-      .view()
+      .view();
 
-    console.log("State:", val)
-  })
-})
+    console.log("State:", val);
+  });
+});

+ 9 - 10
basics/program-derived-addresses/solang/tsconfig.json

@@ -1,11 +1,10 @@
 {
-            "compilerOptions": {
-              "types": ["mocha", "chai"],
-              "typeRoots": ["./node_modules/@types"],
-              "lib": ["es2015"],
-              "module": "commonjs",
-              "target": "es6",
-              "esModuleInterop": true
-            }
-          }
-          
+  "compilerOptions": {
+    "types": ["mocha", "chai"],
+    "typeRoots": ["./node_modules/@types"],
+    "lib": ["es2015"],
+    "module": "commonjs",
+    "target": "es6",
+    "esModuleInterop": true
+  }
+}

+ 0 - 0
basics/rent/solang/solidity/minimum_balance.sol → basics/rent/solang/libraries/minimum_balance.sol


+ 14 - 14
basics/rent/solang/solidity/system_instruction.sol → basics/rent/solang/libraries/system_instruction.sol

@@ -34,7 +34,7 @@ library SystemInstruction {
     /// @param lamports amount of lamports to be transfered to the new account
     /// @param space the size in bytes that is going to be made available for the account
     /// @param owner public key for the program that will own the account being created
-    function create_account(address from, address to, uint64 lamports, uint64 space, address owner) internal view {
+    function create_account(address from, address to, uint64 lamports, uint64 space, address owner) internal {
         AccountMeta[2] metas = [
             AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
             AccountMeta({pubkey: to, is_signer: true, is_writable: true})
@@ -54,7 +54,7 @@ library SystemInstruction {
     /// @param lamports amount of lamports to be transfered to the new account
     /// @param space the size in bytes that is going to be made available for the account
     /// @param owner public key for the program that will own the account being created
-    function create_account_with_seed(address from, address to, address base, string seed, uint64 lamports, uint64 space, address owner) internal view {
+    function create_account_with_seed(address from, address to, address base, string seed, uint64 lamports, uint64 space, address owner) internal {
         AccountMeta[3] metas = [
             AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
             AccountMeta({pubkey: to, is_signer: false, is_writable: true}),
@@ -81,7 +81,7 @@ library SystemInstruction {
     ///
     /// @param pubkey the public key for the account whose owner is going to be reassigned
     /// @param owner the public key for the new account owner
-    function assign(address pubkey, address owner) internal view {
+    function assign(address pubkey, address owner) internal {
         AccountMeta[1] meta = [
             AccountMeta({pubkey: pubkey, is_signer: true, is_writable: true})
         ];
@@ -96,7 +96,7 @@ library SystemInstruction {
     /// @param base the base address that derived the 'addr' key using the seed
     /// @param seed the string utilized to created the 'addr' public key
     /// @param owner the public key for the new program owner
-    function assign_with_seed(address addr, address base, string seed, address owner) internal view {
+    function assign_with_seed(address addr, address base, string seed, address owner) internal {
         AccountMeta[2] metas = [
             AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: base, is_signer: true, is_writable: false})
@@ -119,7 +119,7 @@ library SystemInstruction {
     /// @param from public key for the funding account
     /// @param to public key for the recipient account
     /// @param lamports amount of lamports to transfer
-    function transfer(address from, address to, uint64 lamports) internal view {
+    function transfer(address from, address to, uint64 lamports) internal {
         AccountMeta[2] metas = [
             AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
             AccountMeta({pubkey: to, is_signer: false, is_writable: true})
@@ -138,7 +138,7 @@ library SystemInstruction {
     /// @param from_owner owner to use to derive the funding account address
     /// @param to_pubkey the public key for the recipient account
     /// @param lamports amount of lamports to transfer
-    function transfer_with_seed(address from_pubkey, address from_base, string seed, address from_owner, address to_pubkey, uint64 lamports) internal view {
+    function transfer_with_seed(address from_pubkey, address from_base, string seed, address from_owner, address to_pubkey, uint64 lamports) internal {
         AccountMeta[3] metas = [
             AccountMeta({pubkey: from_pubkey, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: from_base, is_signer: true, is_writable: false}),
@@ -160,7 +160,7 @@ library SystemInstruction {
     ///
     /// @param pub_key account for which to allocate space
     /// @param space number of bytes of memory to allocate
-    function allocate(address pub_key, uint64 space) internal view {
+    function allocate(address pub_key, uint64 space) internal {
         AccountMeta[1] meta = [
             AccountMeta({pubkey: pub_key, is_signer: true, is_writable: true})
         ];
@@ -177,7 +177,7 @@ library SystemInstruction {
     /// @param seed the string utilized to create the 'addr' public key
     /// @param space number of bytes of memory to allocate
     /// @param owner owner to use to derive the 'addr' account address
-    function allocate_with_seed(address addr, address base, string seed, uint64 space, address owner) internal view {
+    function allocate_with_seed(address addr, address base, string seed, uint64 space, address owner) internal {
         AccountMeta[2] metas = [
             AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: base, is_signer: true, is_writable: false})
@@ -204,7 +204,7 @@ library SystemInstruction {
     /// @param seed the string utilized to create the 'addr' public key
     /// @param authority The entity authorized to execute nonce instructions on the account
     /// @param lamports amount of lamports to be transfered to the new account
-    function create_nonce_account_with_seed(address from, address nonce, address base, string seed, address authority, uint64 lamports) internal view {
+    function create_nonce_account_with_seed(address from, address nonce, address base, string seed, address authority, uint64 lamports) internal {
         create_account_with_seed(from, nonce, base, seed, lamports, state_size, systemAddress);
 
         AccountMeta[3] metas = [
@@ -223,7 +223,7 @@ library SystemInstruction {
     /// @param nonce the public key for the nonce account to be created
     /// @param authority The entity authorized to execute nonce instructions on the account
     /// @param lamports amount of lamports to be transfered to the new account
-    function create_nonce_account(address from, address nonce, address authority, uint64 lamports) internal view {
+    function create_nonce_account(address from, address nonce, address authority, uint64 lamports) internal {
         create_account(from, nonce, lamports, state_size, systemAddress);
 
         AccountMeta[3] metas = [
@@ -240,7 +240,7 @@ library SystemInstruction {
     ///
     /// @param nonce_pubkey the public key for the nonce account
     /// @param authorized_pubkey the publick key for the entity authorized to execute instructins on the account
-    function advance_nonce_account(address nonce_pubkey, address authorized_pubkey) internal view {
+    function advance_nonce_account(address nonce_pubkey, address authorized_pubkey) internal {
         AccountMeta[3] metas = [
             AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
@@ -257,7 +257,7 @@ library SystemInstruction {
     /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
     /// @param to_pubkey the recipient account
     /// @param lamports the number of lamports to withdraw
-    function withdraw_nonce_account(address nonce_pubkey, address authorized_pubkey, address to_pubkey, uint64 lamports) internal view {
+    function withdraw_nonce_account(address nonce_pubkey, address authorized_pubkey, address to_pubkey, uint64 lamports) internal {
         AccountMeta[5] metas = [
             AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: to_pubkey, is_signer: false, is_writable: true}),
@@ -275,7 +275,7 @@ library SystemInstruction {
     /// @param nonce_pubkey the public key for the nonce account
     /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
     /// @param new_authority
-    function authorize_nonce_account(address nonce_pubkey, address authorized_pubkey, address new_authority) internal view {
+    function authorize_nonce_account(address nonce_pubkey, address authorized_pubkey, address new_authority) internal {
         AccountMeta[2] metas = [
             AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
@@ -289,7 +289,7 @@ library SystemInstruction {
     ///
     /// @param nonce the public key for the nonce account
     // This is not available on Solana v1.9.15
-    function upgrade_nonce_account(address nonce) internal view {
+    function upgrade_nonce_account(address nonce) internal {
         AccountMeta[1] meta = [
             AccountMeta({pubkey: nonce, is_signer: false, is_writable: true})
         ];

+ 4 - 4
basics/rent/solang/solidity/rent.sol

@@ -1,14 +1,14 @@
 
-import "./system_instruction.sol";
-import 'minimum_balance.sol';
+import "../libraries/system_instruction.sol";
+import '../libraries/minimum_balance.sol';
 
 @program_id("F1ipperKF9EfD821ZbbYjS319LXYiBmjhzkkf5a26rC")
 contract rent {
 
     @payer(payer) // The "payer" pays for the data account creation
-    constructor(address payer) {}
+    constructor() {}
 
-    function createSystemAccount(address payer, address newAccount, uint64 space) public view {
+    function createSystemAccount(address payer, address newAccount, uint64 space) public {
         // The minimum lamports required for the amount of space allocated to the account
         uint64 lamports = minimum_balance(space);
 

+ 19 - 19
basics/rent/solang/tests/rent.ts

@@ -1,34 +1,34 @@
-import * as anchor from "@coral-xyz/anchor"
-import { Program } from "@coral-xyz/anchor"
-import { Rent } from "../target/types/rent"
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { Rent } from "../target/types/rent";
 
 describe("rent", () => {
   // Configure the client to use the local cluster.
-  const provider = anchor.AnchorProvider.env()
-  anchor.setProvider(provider)
+  const provider = anchor.AnchorProvider.env();
+  anchor.setProvider(provider);
 
   // Generate a new keypair for the data account for the program
-  const dataAccount = anchor.web3.Keypair.generate()
-  const wallet = provider.wallet
-  const connection = provider.connection
+  const dataAccount = anchor.web3.Keypair.generate();
+  const wallet = provider.wallet;
+  const connection = provider.connection;
 
-  const program = anchor.workspace.Rent as Program<Rent>
+  const program = anchor.workspace.Rent as Program<Rent>;
 
   it("Is initialized!", async () => {
     // Initialize data account for the program, which is required by Solang
     const tx = await program.methods
-      .new(wallet.publicKey)
+      .new()
       .accounts({ dataAccount: dataAccount.publicKey })
       .signers([dataAccount])
-      .rpc()
-    console.log("Your transaction signature", tx)
-  })
+      .rpc();
+    console.log("Your transaction signature", tx);
+  });
 
   it("Create new account", async () => {
     // Generate a new keypair for the new account
-    const newAccount = anchor.web3.Keypair.generate()
+    const newAccount = anchor.web3.Keypair.generate();
     // Number of bytes of space to allocate for the account
-    const space = 100
+    const space = 100;
 
     // Create a new account via a Cross Program Invocation to the system program
     const tx = await program.methods
@@ -51,7 +51,7 @@ describe("rent", () => {
           isSigner: true,
         },
       ])
-      .rpc()
-    console.log("Your transaction signature", tx)
-  })
-})
+      .rpc();
+    console.log("Your transaction signature", tx);
+  });
+});

+ 9 - 9
basics/rent/solang/tsconfig.json

@@ -1,11 +1,11 @@
 {
-            "compilerOptions": {
-              "types": ["mocha", "chai"],
-              "typeRoots": ["./node_modules/@types"],
-              "lib": ["es2015"],
-              "module": "commonjs",
-              "target": "es6",
-              "esModuleInterop": true
-            }
-          }
+  "compilerOptions": {
+    "types": ["mocha", "chai"],
+    "typeRoots": ["./node_modules/@types"],
+    "lib": ["es2015"],
+    "module": "commonjs",
+    "target": "es6",
+    "esModuleInterop": true
+  }
+}
           

+ 14 - 14
basics/transfer-sol/solang/solidity/system_instruction.sol → basics/transfer-sol/solang/libraries/system_instruction.sol

@@ -34,7 +34,7 @@ library SystemInstruction {
     /// @param lamports amount of lamports to be transfered to the new account
     /// @param space the size in bytes that is going to be made available for the account
     /// @param owner public key for the program that will own the account being created
-    function create_account(address from, address to, uint64 lamports, uint64 space, address owner) internal view {
+    function create_account(address from, address to, uint64 lamports, uint64 space, address owner) internal {
         AccountMeta[2] metas = [
             AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
             AccountMeta({pubkey: to, is_signer: true, is_writable: true})
@@ -54,7 +54,7 @@ library SystemInstruction {
     /// @param lamports amount of lamports to be transfered to the new account
     /// @param space the size in bytes that is going to be made available for the account
     /// @param owner public key for the program that will own the account being created
-    function create_account_with_seed(address from, address to, address base, string seed, uint64 lamports, uint64 space, address owner) internal view {
+    function create_account_with_seed(address from, address to, address base, string seed, uint64 lamports, uint64 space, address owner) internal {
         AccountMeta[3] metas = [
             AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
             AccountMeta({pubkey: to, is_signer: false, is_writable: true}),
@@ -81,7 +81,7 @@ library SystemInstruction {
     ///
     /// @param pubkey the public key for the account whose owner is going to be reassigned
     /// @param owner the public key for the new account owner
-    function assign(address pubkey, address owner) internal view {
+    function assign(address pubkey, address owner) internal {
         AccountMeta[1] meta = [
             AccountMeta({pubkey: pubkey, is_signer: true, is_writable: true})
         ];
@@ -96,7 +96,7 @@ library SystemInstruction {
     /// @param base the base address that derived the 'addr' key using the seed
     /// @param seed the string utilized to created the 'addr' public key
     /// @param owner the public key for the new program owner
-    function assign_with_seed(address addr, address base, string seed, address owner) internal view {
+    function assign_with_seed(address addr, address base, string seed, address owner) internal {
         AccountMeta[2] metas = [
             AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: base, is_signer: true, is_writable: false})
@@ -119,7 +119,7 @@ library SystemInstruction {
     /// @param from public key for the funding account
     /// @param to public key for the recipient account
     /// @param lamports amount of lamports to transfer
-    function transfer(address from, address to, uint64 lamports) internal view {
+    function transfer(address from, address to, uint64 lamports) internal {
         AccountMeta[2] metas = [
             AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
             AccountMeta({pubkey: to, is_signer: false, is_writable: true})
@@ -138,7 +138,7 @@ library SystemInstruction {
     /// @param from_owner owner to use to derive the funding account address
     /// @param to_pubkey the public key for the recipient account
     /// @param lamports amount of lamports to transfer
-    function transfer_with_seed(address from_pubkey, address from_base, string seed, address from_owner, address to_pubkey, uint64 lamports) internal view {
+    function transfer_with_seed(address from_pubkey, address from_base, string seed, address from_owner, address to_pubkey, uint64 lamports) internal {
         AccountMeta[3] metas = [
             AccountMeta({pubkey: from_pubkey, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: from_base, is_signer: true, is_writable: false}),
@@ -160,7 +160,7 @@ library SystemInstruction {
     ///
     /// @param pub_key account for which to allocate space
     /// @param space number of bytes of memory to allocate
-    function allocate(address pub_key, uint64 space) internal view {
+    function allocate(address pub_key, uint64 space) internal {
         AccountMeta[1] meta = [
             AccountMeta({pubkey: pub_key, is_signer: true, is_writable: true})
         ];
@@ -177,7 +177,7 @@ library SystemInstruction {
     /// @param seed the string utilized to create the 'addr' public key
     /// @param space number of bytes of memory to allocate
     /// @param owner owner to use to derive the 'addr' account address
-    function allocate_with_seed(address addr, address base, string seed, uint64 space, address owner) internal view {
+    function allocate_with_seed(address addr, address base, string seed, uint64 space, address owner) internal {
         AccountMeta[2] metas = [
             AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: base, is_signer: true, is_writable: false})
@@ -204,7 +204,7 @@ library SystemInstruction {
     /// @param seed the string utilized to create the 'addr' public key
     /// @param authority The entity authorized to execute nonce instructions on the account
     /// @param lamports amount of lamports to be transfered to the new account
-    function create_nonce_account_with_seed(address from, address nonce, address base, string seed, address authority, uint64 lamports) internal view {
+    function create_nonce_account_with_seed(address from, address nonce, address base, string seed, address authority, uint64 lamports) internal {
         create_account_with_seed(from, nonce, base, seed, lamports, state_size, systemAddress);
 
         AccountMeta[3] metas = [
@@ -223,7 +223,7 @@ library SystemInstruction {
     /// @param nonce the public key for the nonce account to be created
     /// @param authority The entity authorized to execute nonce instructions on the account
     /// @param lamports amount of lamports to be transfered to the new account
-    function create_nonce_account(address from, address nonce, address authority, uint64 lamports) internal view {
+    function create_nonce_account(address from, address nonce, address authority, uint64 lamports) internal {
         create_account(from, nonce, lamports, state_size, systemAddress);
 
         AccountMeta[3] metas = [
@@ -240,7 +240,7 @@ library SystemInstruction {
     ///
     /// @param nonce_pubkey the public key for the nonce account
     /// @param authorized_pubkey the publick key for the entity authorized to execute instructins on the account
-    function advance_nonce_account(address nonce_pubkey, address authorized_pubkey) internal view {
+    function advance_nonce_account(address nonce_pubkey, address authorized_pubkey) internal {
         AccountMeta[3] metas = [
             AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
@@ -257,7 +257,7 @@ library SystemInstruction {
     /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
     /// @param to_pubkey the recipient account
     /// @param lamports the number of lamports to withdraw
-    function withdraw_nonce_account(address nonce_pubkey, address authorized_pubkey, address to_pubkey, uint64 lamports) internal view {
+    function withdraw_nonce_account(address nonce_pubkey, address authorized_pubkey, address to_pubkey, uint64 lamports) internal {
         AccountMeta[5] metas = [
             AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: to_pubkey, is_signer: false, is_writable: true}),
@@ -275,7 +275,7 @@ library SystemInstruction {
     /// @param nonce_pubkey the public key for the nonce account
     /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
     /// @param new_authority
-    function authorize_nonce_account(address nonce_pubkey, address authorized_pubkey, address new_authority) internal view {
+    function authorize_nonce_account(address nonce_pubkey, address authorized_pubkey, address new_authority) internal {
         AccountMeta[2] metas = [
             AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
@@ -289,7 +289,7 @@ library SystemInstruction {
     ///
     /// @param nonce the public key for the nonce account
     // This is not available on Solana v1.9.15
-    function upgrade_nonce_account(address nonce) internal view {
+    function upgrade_nonce_account(address nonce) internal {
         AccountMeta[1] meta = [
             AccountMeta({pubkey: nonce, is_signer: false, is_writable: true})
         ];

+ 3 - 3
basics/transfer-sol/solang/solidity/transfer-sol.sol

@@ -1,16 +1,16 @@
 
-import "./system_instruction.sol";
+import "../libraries/system_instruction.sol";
 
 @program_id("F1ipperKF9EfD821ZbbYjS319LXYiBmjhzkkf5a26rC")
 contract transfer_sol {
 
     @payer(payer) // payer to create new data account
-    constructor(address payer) {
+    constructor() {
         // No data is stored in the account in this example
     }
 
     // Transfer SOL from one account to another using CPI (Cross Program Invocation) to the System program
-    function transferSolWithCpi(address from, address to, uint64 lamports) public view {
+    function transferSolWithCpi(address from, address to, uint64 lamports) public {
         // CPI to transfer SOL using "system_instruction" library
         SystemInstruction.transfer(from, to, lamports);
     }

+ 37 - 37
basics/transfer-sol/solang/tests/transfer-sol.ts

@@ -1,39 +1,39 @@
-import * as anchor from "@coral-xyz/anchor"
-import { Program } from "@coral-xyz/anchor"
-import { TransferSol } from "../target/types/transfer_sol"
-import { PublicKey } from "@solana/web3.js"
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { TransferSol } from "../target/types/transfer_sol";
+import { PublicKey } from "@solana/web3.js";
 
 describe("transfer-sol", () => {
   // Configure the client to use the local cluster.
-  const provider = anchor.AnchorProvider.env()
-  anchor.setProvider(provider)
+  const provider = anchor.AnchorProvider.env();
+  anchor.setProvider(provider);
 
   // Generate new keypair to use as data account
-  const dataAccount = anchor.web3.Keypair.generate()
-  const wallet = provider.wallet
-  const connection = provider.connection
+  const dataAccount = anchor.web3.Keypair.generate();
+  const wallet = provider.wallet;
+  const connection = provider.connection;
 
-  const program = anchor.workspace.TransferSol as Program<TransferSol>
+  const program = anchor.workspace.TransferSol as Program<TransferSol>;
 
   // Amount to transfer in lamports
-  const transferAmount = 1 * anchor.web3.LAMPORTS_PER_SOL // 1 SOL
+  const transferAmount = 1 * anchor.web3.LAMPORTS_PER_SOL; // 1 SOL
 
   it("Is initialized!", async () => {
     // Create the new data account
     // The dataAccount is required by Solang even though it is not use in the transfer instruction
     const tx = await program.methods
-      .new(wallet.publicKey) // payer
+      .new()
       .accounts({ dataAccount: dataAccount.publicKey })
       .signers([dataAccount])
-      .rpc()
-    console.log("Your transaction signature", tx)
-  })
+      .rpc();
+    console.log("Your transaction signature", tx);
+  });
 
   it("Transfer SOL using CPI to the system program", async () => {
     // Generate new keypair to use as recipient for the transfer
-    const recipient = anchor.web3.Keypair.generate() // test1 recipient
+    const recipient = anchor.web3.Keypair.generate(); // test1 recipient
 
-    await getBalances(wallet.publicKey, recipient.publicKey, "Beginning")
+    await getBalances(wallet.publicKey, recipient.publicKey, "Beginning");
 
     const tx = await program.methods
       .transferSolWithCpi(
@@ -54,15 +54,15 @@ describe("transfer-sol", () => {
           isSigner: false,
         },
       ])
-      .rpc()
+      .rpc();
 
-    await getBalances(wallet.publicKey, recipient.publicKey, "Resulting")
+    await getBalances(wallet.publicKey, recipient.publicKey, "Resulting");
 
-    console.log("Your transaction signature", tx)
-  })
+    console.log("Your transaction signature", tx);
+  });
 
   it("Transfer SOL to program owned account", async () => {
-    await getBalances(wallet.publicKey, dataAccount.publicKey, "Beginning")
+    await getBalances(wallet.publicKey, dataAccount.publicKey, "Beginning");
 
     const tx = await program.methods
       .transferSolWithCpi(
@@ -83,15 +83,15 @@ describe("transfer-sol", () => {
           isSigner: false,
         },
       ])
-      .rpc()
+      .rpc();
 
-    await getBalances(wallet.publicKey, dataAccount.publicKey, "Resulting")
+    await getBalances(wallet.publicKey, dataAccount.publicKey, "Resulting");
 
-    console.log("Your transaction signature", tx)
-  })
+    console.log("Your transaction signature", tx);
+  });
 
   it("Transfer SOL from program owned account", async () => {
-    await getBalances(dataAccount.publicKey, wallet.publicKey, "Beginning")
+    await getBalances(dataAccount.publicKey, wallet.publicKey, "Beginning");
 
     const tx = await program.methods
       .transferSolWithProgram(
@@ -105,12 +105,12 @@ describe("transfer-sol", () => {
           isSigner: true,
         },
       ])
-      .rpc()
+      .rpc();
 
-    await getBalances(dataAccount.publicKey, wallet.publicKey, "Resulting")
+    await getBalances(dataAccount.publicKey, wallet.publicKey, "Resulting");
 
-    console.log("Your transaction signature", tx)
-  })
+    console.log("Your transaction signature", tx);
+  });
 
   // Helper function to get balances and log them to the console
   async function getBalances(
@@ -118,12 +118,12 @@ describe("transfer-sol", () => {
     recipientPubkey: PublicKey,
     timeframe: string
   ) {
-    let payerBalance = await connection.getBalance(payerPubkey)
-    let recipientBalance = await connection.getBalance(recipientPubkey)
-    console.log(`${timeframe} balances:`)
-    console.log(`   Payer: ${payerBalance / anchor.web3.LAMPORTS_PER_SOL}`) // convert lamports to SOL
+    let payerBalance = await connection.getBalance(payerPubkey);
+    let recipientBalance = await connection.getBalance(recipientPubkey);
+    console.log(`${timeframe} balances:`);
+    console.log(`   Payer: ${payerBalance / anchor.web3.LAMPORTS_PER_SOL}`); // convert lamports to SOL
     console.log(
       `   Recipient: ${recipientBalance / anchor.web3.LAMPORTS_PER_SOL}` // convert lamports to SOL
-    )
+    );
   }
-})
+});

+ 8 - 0
compression/cnft-solang/.gitignore

@@ -0,0 +1,8 @@
+
+.anchor
+.DS_Store
+target
+**/*.rs.bk
+node_modules
+test-ledger
+.yarn

+ 8 - 0
compression/cnft-solang/.prettierignore

@@ -0,0 +1,8 @@
+
+.anchor
+.DS_Store
+target
+node_modules
+dist
+build
+test-ledger

+ 30 - 0
compression/cnft-solang/Anchor.toml

@@ -0,0 +1,30 @@
+[features]
+seeds = false
+skip-lint = false
+[programs.devnet]
+compressed_nft = "BhDH6TLEnf4dLq9hLn2gLwm5rJdj8Cbdc9ZrsjUpL7kB"
+
+[registry]
+url = "https://api.apr.dev"
+
+[provider]
+cluster = "devnet"
+wallet = "~/.config/solana/id.json"
+
+[scripts]
+test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
+
+[test.validator]
+url = "https://api.mainnet-beta.solana.com"
+
+[[test.validator.clone]]
+address = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
+
+[[test.validator.clone]]
+address = "BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY"
+
+[[test.validator.clone]]
+address = "noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV"
+
+[[test.validator.clone]]
+address = "cmtDvXumGCrqC1Age74AVPhSRVXJMd8PJS91L8KbNCK"

+ 3 - 0
compression/cnft-solang/app/.eslintrc.json

@@ -0,0 +1,3 @@
+{
+  "extends": "next/core-web-vitals"
+}

+ 37 - 0
compression/cnft-solang/app/.gitignore

@@ -0,0 +1,37 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
+
+package-lock.json

+ 38 - 0
compression/cnft-solang/app/README.md

@@ -0,0 +1,38 @@
+This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
+
+## Getting Started
+
+First, run the development server:
+
+```bash
+npm run dev
+# or
+yarn dev
+# or
+pnpm dev
+```
+
+Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+
+You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.
+
+[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
+
+The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
+
+This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
+
+## Learn More
+
+To learn more about Next.js, take a look at the following resources:
+
+- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
+- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
+
+You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
+
+## Deploy on Vercel
+
+The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
+
+Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

+ 30 - 0
compression/cnft-solang/app/components/Confirmed.tsx

@@ -0,0 +1,30 @@
+import { useEffect, useState } from "react"
+import { buildStyles, CircularProgressbar } from "react-circular-progressbar"
+import "react-circular-progressbar/dist/styles.css"
+
+const Confirmed = () => {
+  const [percentage, setPercentage] = useState(0)
+  const [text, setText] = useState("😋")
+
+  useEffect(() => {
+    const t1 = setTimeout(() => setPercentage(100), 100)
+    const t2 = setTimeout(() => setText("✅"), 600)
+
+    return () => {
+      clearTimeout(t1)
+      clearTimeout(t2)
+    }
+  }, [])
+
+  return (
+    <CircularProgressbar
+      value={percentage}
+      text={text}
+      styles={buildStyles({
+        pathColor: "#19fb9b",
+      })}
+    />
+  )
+}
+
+export default Confirmed

+ 108 - 0
compression/cnft-solang/app/components/QrCodeCnftMint.tsx

@@ -0,0 +1,108 @@
+import { Button, Flex, VStack } from "@chakra-ui/react"
+import {
+  createQR,
+  encodeURL,
+  findReference,
+  FindReferenceError,
+  TransactionRequestURLFields,
+  ValidateTransferError,
+} from "@solana/pay"
+import { clusterApiUrl, Connection, Keypair } from "@solana/web3.js"
+import { useEffect, useRef, useState } from "react"
+import Confirmed from "./Confirmed"
+
+interface Props {
+  onClose: () => void
+}
+
+const QrModal = ({ onClose }: Props) => {
+  const [confirmed, setConfirmed] = useState(false)
+  const connection = new Connection(clusterApiUrl("devnet"))
+  const qrRef = useRef<HTMLDivElement>(null)
+  const [reference] = useState(Keypair.generate().publicKey)
+
+  const [size, setSize] = useState(() =>
+    typeof window === "undefined" ? 100 : Math.min(window.outerWidth - 10, 512)
+  )
+
+  useEffect(() => {
+    const listener = () => setSize(Math.min(window.outerWidth - 10, 512))
+    window.addEventListener("resize", listener)
+    return () => window.removeEventListener("resize", listener)
+  }, [])
+
+  useEffect(() => {
+    const { location } = window
+    const params = new URLSearchParams()
+    params.append("reference", reference.toString())
+
+    const apiUrl = `${location.protocol}//${
+      location.host
+    }/api/mintCnft?${params.toString()}`
+    const urlParams: TransactionRequestURLFields = {
+      link: new URL(apiUrl),
+      label: "Label",
+      message: "Message",
+    }
+    const solanaUrl = encodeURL(urlParams)
+    console.log(solanaUrl)
+    const qr = createQR(solanaUrl, size, "white")
+    if (qrRef.current) {
+      qrRef.current.innerHTML = ""
+      qr.append(qrRef.current)
+    }
+  }, [window, size, reference])
+
+  useEffect(() => {
+    const interval = setInterval(async () => {
+      try {
+        const signatureInfo = await findReference(connection, reference, {
+          finality: "confirmed",
+        })
+        setConfirmed(true)
+      } catch (e) {
+        if (e instanceof FindReferenceError) return
+        if (e instanceof ValidateTransferError) {
+          console.error("Transaction is invalid", e)
+          return
+        }
+        console.error("Unknown error", e)
+      }
+    }, 500)
+    return () => {
+      clearInterval(interval)
+      setConfirmed(false)
+    }
+  }, [reference.toString()])
+
+  return (
+    <VStack
+      position="fixed"
+      top="50%"
+      left="50%"
+      transform="translate(-50%, -50%)"
+      backgroundColor="white"
+      padding="10px"
+      rounded="2xl"
+    >
+      {confirmed ? (
+        <div style={{ width: size }}>
+          <Confirmed />
+        </div>
+      ) : (
+        <Flex ref={qrRef} />
+      )}
+      <Button
+        color="gray"
+        onClick={() => {
+          setConfirmed(false)
+          onClose()
+        }}
+      >
+        Close
+      </Button>
+    </VStack>
+  )
+}
+
+export default QrModal

+ 13 - 0
compression/cnft-solang/app/components/WalletMultiButton.tsx

@@ -0,0 +1,13 @@
+import dynamic from "next/dynamic"
+
+export const WalletMultiButtonDynamic = dynamic(
+  async () =>
+    (await import("@solana/wallet-adapter-react-ui")).WalletMultiButton,
+  { ssr: false }
+)
+
+const WalletMultiButton = () => {
+  return <WalletMultiButtonDynamic />
+}
+
+export default WalletMultiButton

+ 38 - 0
compression/cnft-solang/app/contexts/WalletContextProvider.tsx

@@ -0,0 +1,38 @@
+import { FC, ReactNode, useMemo } from "react"
+import { WalletAdapterNetwork } from "@solana/wallet-adapter-base"
+import {
+  ConnectionProvider,
+  WalletProvider,
+} from "@solana/wallet-adapter-react"
+import { WalletModalProvider } from "@solana/wallet-adapter-react-ui"
+import {
+  PhantomWalletAdapter,
+  SolflareWalletAdapter,
+  BackpackWalletAdapter,
+} from "@solana/wallet-adapter-wallets"
+import { clusterApiUrl } from "@solana/web3.js"
+require("@solana/wallet-adapter-react-ui/styles.css")
+
+const WalletContextProvider: FC<{ children: ReactNode }> = ({ children }) => {
+  const network = WalletAdapterNetwork.Devnet
+  const endpoint = useMemo(() => clusterApiUrl(network), [network])
+
+  const wallets = useMemo(
+    () => [
+      new BackpackWalletAdapter(),
+      new PhantomWalletAdapter(),
+      new SolflareWalletAdapter(),
+    ],
+    [network]
+  )
+
+  return (
+    <ConnectionProvider endpoint={endpoint}>
+      <WalletProvider wallets={wallets} autoConnect>
+        <WalletModalProvider>{children}</WalletModalProvider>
+      </WalletProvider>
+    </ConnectionProvider>
+  )
+}
+
+export default WalletContextProvider

+ 175 - 0
compression/cnft-solang/app/idl/compressed_nft.ts

@@ -0,0 +1,175 @@
+export type CompressedNft = {
+  version: "0.3.1";
+  name: "compressed_nft";
+  instructions: [
+    {
+      name: "new";
+      accounts: [
+        {
+          name: "dataAccount";
+          isMut: true;
+          isSigner: false;
+          isOptional: false;
+        },
+        {
+          name: "payer";
+          isMut: true;
+          isSigner: true;
+          isOptional: false;
+        },
+        {
+          name: "systemProgram";
+          isMut: false;
+          isSigner: false;
+          isOptional: false;
+        }
+      ];
+      args: [
+        {
+          name: "bump";
+          type: {
+            array: ["u8", 1];
+          };
+        }
+      ];
+    },
+    {
+      name: "mint";
+      accounts: [
+        {
+          name: "dataAccount";
+          isMut: true;
+          isSigner: false;
+          isOptional: false;
+        },
+        {
+          name: "systemProgram";
+          isMut: false;
+          isSigner: false;
+          isOptional: false;
+        }
+      ];
+      args: [
+        {
+          name: "treeAuthority";
+          type: "publicKey";
+        },
+        {
+          name: "leafOwner";
+          type: "publicKey";
+        },
+        {
+          name: "leafDelegate";
+          type: "publicKey";
+        },
+        {
+          name: "merkleTree";
+          type: "publicKey";
+        },
+        {
+          name: "payer";
+          type: "publicKey";
+        },
+        {
+          name: "treeDelegate";
+          type: "publicKey";
+        },
+        {
+          name: "uri";
+          type: "string";
+        }
+      ];
+    }
+  ];
+  metadata: {
+    address: "BhDH6TLEnf4dLq9hLn2gLwm5rJdj8Cbdc9ZrsjUpL7kB";
+  };
+};
+
+export const IDL: CompressedNft = {
+  version: "0.3.1",
+  name: "compressed_nft",
+  instructions: [
+    {
+      name: "new",
+      accounts: [
+        {
+          name: "dataAccount",
+          isMut: true,
+          isSigner: false,
+          isOptional: false,
+        },
+        {
+          name: "payer",
+          isMut: true,
+          isSigner: true,
+          isOptional: false,
+        },
+        {
+          name: "systemProgram",
+          isMut: false,
+          isSigner: false,
+          isOptional: false,
+        },
+      ],
+      args: [
+        {
+          name: "bump",
+          type: {
+            array: ["u8", 1],
+          },
+        },
+      ],
+    },
+    {
+      name: "mint",
+      accounts: [
+        {
+          name: "dataAccount",
+          isMut: true,
+          isSigner: false,
+          isOptional: false,
+        },
+        {
+          name: "systemProgram",
+          isMut: false,
+          isSigner: false,
+          isOptional: false,
+        },
+      ],
+      args: [
+        {
+          name: "treeAuthority",
+          type: "publicKey",
+        },
+        {
+          name: "leafOwner",
+          type: "publicKey",
+        },
+        {
+          name: "leafDelegate",
+          type: "publicKey",
+        },
+        {
+          name: "merkleTree",
+          type: "publicKey",
+        },
+        {
+          name: "payer",
+          type: "publicKey",
+        },
+        {
+          name: "treeDelegate",
+          type: "publicKey",
+        },
+        {
+          name: "uri",
+          type: "string",
+        },
+      ],
+    },
+  ],
+  metadata: {
+    address: "BhDH6TLEnf4dLq9hLn2gLwm5rJdj8Cbdc9ZrsjUpL7kB",
+  },
+};

+ 6 - 0
compression/cnft-solang/app/next.config.js

@@ -0,0 +1,6 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {
+  reactStrictMode: true,
+}
+
+module.exports = nextConfig

+ 36 - 0
compression/cnft-solang/app/package.json

@@ -0,0 +1,36 @@
+{
+  "name": "wallet-adapter-chakraui-nextjs",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "dev": "next dev",
+    "build": "next build",
+    "start": "next start",
+    "lint": "next lint"
+  },
+  "dependencies": {
+    "@chakra-ui/next-js": "^2.1.3",
+    "@chakra-ui/react": "^2.6.1",
+    "@emotion/react": "^11.11.0",
+    "@emotion/styled": "^11.11.0",
+    "@metaplex-foundation/mpl-bubblegum": "^0.7.0",
+    "@solana/pay": "^0.2.5",
+    "@solana/spl-account-compression": "^0.1.8",
+    "@solana/wallet-adapter-base": "^0.9.22",
+    "@solana/wallet-adapter-react": "^0.15.32",
+    "@solana/wallet-adapter-react-ui": "^0.9.31",
+    "@solana/wallet-adapter-wallets": "^0.19.16",
+    "@solana/web3.js": "^1.77.1",
+    "@types/node": "20.2.5",
+    "@types/react": "18.2.7",
+    "@types/react-dom": "18.2.4",
+    "eslint": "8.41.0",
+    "eslint-config-next": "13.4.4",
+    "framer-motion": "^10.12.16",
+    "next": "13.4.4",
+    "react": "18.2.0",
+    "react-circular-progressbar": "^2.1.0",
+    "react-dom": "18.2.0",
+    "typescript": "5.0.4"
+  }
+}

+ 13 - 0
compression/cnft-solang/app/pages/_app.tsx

@@ -0,0 +1,13 @@
+import { ChakraProvider } from "@chakra-ui/react"
+import WalletContextProvider from "../contexts/WalletContextProvider"
+import type { AppProps } from "next/app"
+
+export default function App({ Component, pageProps }: AppProps) {
+  return (
+    <ChakraProvider>
+      <WalletContextProvider>
+        <Component {...pageProps} />
+      </WalletContextProvider>
+    </ChakraProvider>
+  )
+}

+ 13 - 0
compression/cnft-solang/app/pages/_document.tsx

@@ -0,0 +1,13 @@
+import { Html, Head, Main, NextScript } from 'next/document'
+
+export default function Document() {
+  return (
+    <Html lang="en">
+      <Head />
+      <body>
+        <Main />
+        <NextScript />
+      </body>
+    </Html>
+  )
+}

+ 145 - 0
compression/cnft-solang/app/pages/api/mintCnft.ts

@@ -0,0 +1,145 @@
+import { NextApiRequest, NextApiResponse } from "next"
+import { PublicKey, SystemProgram, Transaction } from "@solana/web3.js"
+import {
+  SPL_ACCOUNT_COMPRESSION_PROGRAM_ID,
+  SPL_NOOP_PROGRAM_ID,
+} from "@solana/spl-account-compression"
+import { PROGRAM_ID as BUBBLEGUM_PROGRAM_ID } from "@metaplex-foundation/mpl-bubblegum"
+import { program, connection, treeAddress } from "@/utils/setup"
+import { uris } from "@/utils/uri"
+
+function get(res: NextApiResponse) {
+  res.status(200).json({
+    label: "My Store",
+    icon: "https://solana.com/src/img/branding/solanaLogoMark.svg",
+  })
+}
+
+async function post(req: NextApiRequest, res: NextApiResponse) {
+  const { account } = req.body
+  const { reference } = req.query
+
+  if (!account || !reference) {
+    res.status(400).json({
+      error: "Required data missing. Account or reference not provided.",
+    })
+    return
+  }
+
+  try {
+    const transaction = await buildTransaction(
+      new PublicKey(account),
+      new PublicKey(reference)
+    )
+    res.status(200).json({
+      transaction,
+      message: "Please approve the transaction to mint your NFT!",
+    })
+  } catch (error) {
+    console.error(error)
+    res.status(500).json({ error: "error creating transaction" })
+    return
+  }
+}
+
+async function buildTransaction(account: PublicKey, reference: PublicKey) {
+  // Required solang dataAccount, even though we're not using it.
+  const [dataAccount] = PublicKey.findProgramAddressSync(
+    [Buffer.from("seed")],
+    program.programId
+  )
+
+  // tree authority
+  const [treeAuthority] = PublicKey.findProgramAddressSync(
+    [treeAddress.toBuffer()],
+    BUBBLEGUM_PROGRAM_ID
+  )
+
+  // Randomly select a uri.
+  const randomUri = uris[Math.floor(Math.random() * uris.length)]
+
+  // Initialize the dataAccount.
+  const instruction = await program.methods
+    .mint(
+      treeAuthority, // treeAuthority
+      account, // leafOwner
+      account, // leafDelegate
+      treeAddress, // merkleTree
+      account, // payer
+      account, // treeDelegate, public tree (no delegate check, just require signer)
+      randomUri // uri
+    )
+    .accounts({ dataAccount: dataAccount })
+    .remainingAccounts([
+      {
+        pubkey: account,
+        isWritable: true,
+        isSigner: true,
+      },
+      {
+        pubkey: treeAuthority,
+        isWritable: true,
+        isSigner: false,
+      },
+      {
+        pubkey: treeAddress,
+        isWritable: true,
+        isSigner: false,
+      },
+      {
+        pubkey: SPL_NOOP_PROGRAM_ID,
+        isWritable: false,
+        isSigner: false,
+      },
+      {
+        pubkey: SPL_ACCOUNT_COMPRESSION_PROGRAM_ID,
+        isWritable: false,
+        isSigner: false,
+      },
+      {
+        pubkey: BUBBLEGUM_PROGRAM_ID,
+        isWritable: false,
+        isSigner: false,
+      },
+      {
+        pubkey: SystemProgram.programId,
+        isWritable: false,
+        isSigner: false,
+      },
+    ])
+    .instruction()
+
+  // Add the reference account to the instruction
+  // Used in client to find the transaction once sent
+  instruction.keys.push({
+    pubkey: reference,
+    isSigner: false,
+    isWritable: false,
+  })
+
+  const latestBlockhash = await connection.getLatestBlockhash()
+
+  // create new Transaction and add instruction
+  const transaction = new Transaction({
+    feePayer: account,
+    blockhash: latestBlockhash.blockhash,
+    lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
+  }).add(instruction)
+
+  return transaction
+    .serialize({ requireAllSignatures: false })
+    .toString("base64")
+}
+
+export default async function handler(
+  req: NextApiRequest,
+  res: NextApiResponse
+) {
+  if (req.method === "GET") {
+    return get(res)
+  } else if (req.method === "POST") {
+    return await post(req, res)
+  } else {
+    return res.status(405).json({ error: "Method not allowed" })
+  }
+}

+ 25 - 0
compression/cnft-solang/app/pages/index.tsx

@@ -0,0 +1,25 @@
+import {
+  Box,
+  Button,
+  Flex,
+  Spacer,
+  VStack,
+  useDisclosure,
+} from "@chakra-ui/react"
+import WalletMultiButton from "@/components/WalletMultiButton"
+import QrModal from "@/components/QrCodeCnftMint"
+export default function Home() {
+  const { isOpen, onOpen, onClose } = useDisclosure()
+  return (
+    <Box>
+      <Flex px={4} py={4}>
+        <Spacer />
+        <WalletMultiButton />
+      </Flex>
+      <VStack justifyContent="center">
+        <Button onClick={onOpen}>Solana Pay Mint</Button>
+        {isOpen && <QrModal onClose={onClose} />}
+      </VStack>
+    </Box>
+  )
+}

BIN
compression/cnft-solang/app/public/favicon.ico


+ 1 - 0
compression/cnft-solang/app/public/next.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>

+ 1 - 0
compression/cnft-solang/app/public/vercel.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 283 64"><path fill="black" d="M141 16c-11 0-19 7-19 18s9 18 20 18c7 0 13-3 16-7l-7-5c-2 3-6 4-9 4-5 0-9-3-10-7h28v-3c0-11-8-18-19-18zm-9 15c1-4 4-7 9-7s8 3 9 7h-18zm117-15c-11 0-19 7-19 18s9 18 20 18c6 0 12-3 16-7l-8-5c-2 3-5 4-8 4-5 0-9-3-11-7h28l1-3c0-11-8-18-19-18zm-10 15c2-4 5-7 10-7s8 3 9 7h-19zm-39 3c0 6 4 10 10 10 4 0 7-2 9-5l8 5c-3 5-9 8-17 8-11 0-19-7-19-18s8-18 19-18c8 0 14 3 17 8l-8 5c-2-3-5-5-9-5-6 0-10 4-10 10zm83-29v46h-9V5h9zM37 0l37 64H0L37 0zm92 5-27 48L74 5h10l18 30 17-30h10zm59 12v10l-3-1c-6 0-10 4-10 10v15h-9V17h9v9c0-5 6-9 13-9z"/></svg>

+ 229 - 0
compression/cnft-solang/app/styles/Home.module.css

@@ -0,0 +1,229 @@
+.main {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+  align-items: center;
+  padding: 6rem;
+  min-height: 100vh;
+}
+
+.description {
+  display: inherit;
+  justify-content: inherit;
+  align-items: inherit;
+  font-size: 0.85rem;
+  max-width: var(--max-width);
+  width: 100%;
+  z-index: 2;
+  font-family: var(--font-mono);
+}
+
+.description a {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  gap: 0.5rem;
+}
+
+.description p {
+  position: relative;
+  margin: 0;
+  padding: 1rem;
+  background-color: rgba(var(--callout-rgb), 0.5);
+  border: 1px solid rgba(var(--callout-border-rgb), 0.3);
+  border-radius: var(--border-radius);
+}
+
+.code {
+  font-weight: 700;
+  font-family: var(--font-mono);
+}
+
+.grid {
+  display: grid;
+  grid-template-columns: repeat(4, minmax(25%, auto));
+  width: var(--max-width);
+  max-width: 100%;
+}
+
+.card {
+  padding: 1rem 1.2rem;
+  border-radius: var(--border-radius);
+  background: rgba(var(--card-rgb), 0);
+  border: 1px solid rgba(var(--card-border-rgb), 0);
+  transition: background 200ms, border 200ms;
+}
+
+.card span {
+  display: inline-block;
+  transition: transform 200ms;
+}
+
+.card h2 {
+  font-weight: 600;
+  margin-bottom: 0.7rem;
+}
+
+.card p {
+  margin: 0;
+  opacity: 0.6;
+  font-size: 0.9rem;
+  line-height: 1.5;
+  max-width: 30ch;
+}
+
+.center {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  position: relative;
+  padding: 4rem 0;
+}
+
+.center::before {
+  background: var(--secondary-glow);
+  border-radius: 50%;
+  width: 480px;
+  height: 360px;
+  margin-left: -400px;
+}
+
+.center::after {
+  background: var(--primary-glow);
+  width: 240px;
+  height: 180px;
+  z-index: -1;
+}
+
+.center::before,
+.center::after {
+  content: '';
+  left: 50%;
+  position: absolute;
+  filter: blur(45px);
+  transform: translateZ(0);
+}
+
+.logo {
+  position: relative;
+}
+/* Enable hover only on non-touch devices */
+@media (hover: hover) and (pointer: fine) {
+  .card:hover {
+    background: rgba(var(--card-rgb), 0.1);
+    border: 1px solid rgba(var(--card-border-rgb), 0.15);
+  }
+
+  .card:hover span {
+    transform: translateX(4px);
+  }
+}
+
+@media (prefers-reduced-motion) {
+  .card:hover span {
+    transform: none;
+  }
+}
+
+/* Mobile */
+@media (max-width: 700px) {
+  .content {
+    padding: 4rem;
+  }
+
+  .grid {
+    grid-template-columns: 1fr;
+    margin-bottom: 120px;
+    max-width: 320px;
+    text-align: center;
+  }
+
+  .card {
+    padding: 1rem 2.5rem;
+  }
+
+  .card h2 {
+    margin-bottom: 0.5rem;
+  }
+
+  .center {
+    padding: 8rem 0 6rem;
+  }
+
+  .center::before {
+    transform: none;
+    height: 300px;
+  }
+
+  .description {
+    font-size: 0.8rem;
+  }
+
+  .description a {
+    padding: 1rem;
+  }
+
+  .description p,
+  .description div {
+    display: flex;
+    justify-content: center;
+    position: fixed;
+    width: 100%;
+  }
+
+  .description p {
+    align-items: center;
+    inset: 0 0 auto;
+    padding: 2rem 1rem 1.4rem;
+    border-radius: 0;
+    border: none;
+    border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25);
+    background: linear-gradient(
+      to bottom,
+      rgba(var(--background-start-rgb), 1),
+      rgba(var(--callout-rgb), 0.5)
+    );
+    background-clip: padding-box;
+    backdrop-filter: blur(24px);
+  }
+
+  .description div {
+    align-items: flex-end;
+    pointer-events: none;
+    inset: auto 0 0;
+    padding: 2rem;
+    height: 200px;
+    background: linear-gradient(
+      to bottom,
+      transparent 0%,
+      rgb(var(--background-end-rgb)) 40%
+    );
+    z-index: 1;
+  }
+}
+
+/* Tablet and Smaller Desktop */
+@media (min-width: 701px) and (max-width: 1120px) {
+  .grid {
+    grid-template-columns: repeat(2, 50%);
+  }
+}
+
+@media (prefers-color-scheme: dark) {
+  .vercelLogo {
+    filter: invert(1);
+  }
+
+  .logo {
+    filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70);
+  }
+}
+
+@keyframes rotate {
+  from {
+    transform: rotate(360deg);
+  }
+  to {
+    transform: rotate(0deg);
+  }
+}

+ 107 - 0
compression/cnft-solang/app/styles/globals.css

@@ -0,0 +1,107 @@
+:root {
+  --max-width: 1100px;
+  --border-radius: 12px;
+  --font-mono: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono',
+    'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro',
+    'Fira Mono', 'Droid Sans Mono', 'Courier New', monospace;
+
+  --foreground-rgb: 0, 0, 0;
+  --background-start-rgb: 214, 219, 220;
+  --background-end-rgb: 255, 255, 255;
+
+  --primary-glow: conic-gradient(
+    from 180deg at 50% 50%,
+    #16abff33 0deg,
+    #0885ff33 55deg,
+    #54d6ff33 120deg,
+    #0071ff33 160deg,
+    transparent 360deg
+  );
+  --secondary-glow: radial-gradient(
+    rgba(255, 255, 255, 1),
+    rgba(255, 255, 255, 0)
+  );
+
+  --tile-start-rgb: 239, 245, 249;
+  --tile-end-rgb: 228, 232, 233;
+  --tile-border: conic-gradient(
+    #00000080,
+    #00000040,
+    #00000030,
+    #00000020,
+    #00000010,
+    #00000010,
+    #00000080
+  );
+
+  --callout-rgb: 238, 240, 241;
+  --callout-border-rgb: 172, 175, 176;
+  --card-rgb: 180, 185, 188;
+  --card-border-rgb: 131, 134, 135;
+}
+
+@media (prefers-color-scheme: dark) {
+  :root {
+    --foreground-rgb: 255, 255, 255;
+    --background-start-rgb: 0, 0, 0;
+    --background-end-rgb: 0, 0, 0;
+
+    --primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0));
+    --secondary-glow: linear-gradient(
+      to bottom right,
+      rgba(1, 65, 255, 0),
+      rgba(1, 65, 255, 0),
+      rgba(1, 65, 255, 0.3)
+    );
+
+    --tile-start-rgb: 2, 13, 46;
+    --tile-end-rgb: 2, 5, 19;
+    --tile-border: conic-gradient(
+      #ffffff80,
+      #ffffff40,
+      #ffffff30,
+      #ffffff20,
+      #ffffff10,
+      #ffffff10,
+      #ffffff80
+    );
+
+    --callout-rgb: 20, 20, 20;
+    --callout-border-rgb: 108, 108, 108;
+    --card-rgb: 100, 100, 100;
+    --card-border-rgb: 200, 200, 200;
+  }
+}
+
+* {
+  box-sizing: border-box;
+  padding: 0;
+  margin: 0;
+}
+
+html,
+body {
+  max-width: 100vw;
+  overflow-x: hidden;
+}
+
+body {
+  color: rgb(var(--foreground-rgb));
+  background: linear-gradient(
+      to bottom,
+      transparent,
+      rgb(var(--background-end-rgb))
+    )
+    rgb(var(--background-start-rgb));
+}
+
+a {
+  color: inherit;
+  text-decoration: none;
+}
+
+@media (prefers-color-scheme: dark) {
+  html {
+    color-scheme: dark;
+  }
+}

+ 23 - 0
compression/cnft-solang/app/tsconfig.json

@@ -0,0 +1,23 @@
+{
+  "compilerOptions": {
+    "target": "es5",
+    "lib": ["dom", "dom.iterable", "esnext"],
+    "allowJs": true,
+    "skipLibCheck": true,
+    "strict": true,
+    "forceConsistentCasingInFileNames": true,
+    "noEmit": true,
+    "esModuleInterop": true,
+    "module": "esnext",
+    "moduleResolution": "node",
+    "resolveJsonModule": true,
+    "isolatedModules": true,
+    "jsx": "preserve",
+    "incremental": true,
+    "paths": {
+      "@/*": ["./*"]
+    }
+  },
+  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
+  "exclude": ["node_modules"]
+}

+ 15 - 0
compression/cnft-solang/app/utils/setup.ts

@@ -0,0 +1,15 @@
+import { Program, Idl } from "@coral-xyz/anchor";
+import { IDL, CompressedNft } from "../idl/compressed_nft";
+import { clusterApiUrl, Connection, PublicKey } from "@solana/web3.js";
+
+export const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
+
+const programId = IDL.metadata.address;
+
+export const program = new Program(IDL as Idl, programId, {
+  connection,
+}) as unknown as Program<CompressedNft>;
+
+export const treeAddress = new PublicKey(
+  "FYwZ4rMtexsHBTx2aCnQRVg51K5WXZJ1n3SYacXFvado"
+);

+ 12 - 0
compression/cnft-solang/app/utils/uri.ts

@@ -0,0 +1,12 @@
+export const uris = [
+  "https://raw.githubusercontent.com/ZYJLiu/rgb-png-generator/master/assets/40_183_132/40_183_132.json",
+  "https://raw.githubusercontent.com/ZYJLiu/rgb-png-generator/master/assets/12_217_47/12_217_47.json",
+  "https://raw.githubusercontent.com/ZYJLiu/rgb-png-generator/master/assets/255_68_196/255_68_196.json",
+  "https://raw.githubusercontent.com/ZYJLiu/rgb-png-generator/master/assets/156_61_27/156_61_27.json",
+  "https://raw.githubusercontent.com/ZYJLiu/rgb-png-generator/master/assets/32_150_152/32_150_152.json",
+  "https://raw.githubusercontent.com/ZYJLiu/rgb-png-generator/master/assets/78_96_197/78_96_197.json",
+  "https://raw.githubusercontent.com/ZYJLiu/rgb-png-generator/master/assets/38_47_11/38_47_11.json",
+  "https://raw.githubusercontent.com/ZYJLiu/rgb-png-generator/master/assets/190_85_238/190_85_238.json",
+  "https://raw.githubusercontent.com/ZYJLiu/rgb-png-generator/master/assets/69_46_192/69_46_192.json",
+  "https://raw.githubusercontent.com/ZYJLiu/rgb-png-generator/master/assets/142_17_9/142_17_9.json",
+]

+ 12 - 0
compression/cnft-solang/migrations/deploy.ts

@@ -0,0 +1,12 @@
+// Migrations are an early feature. Currently, they're nothing more than this
+// single deploy script that's invoked from the CLI, injecting a provider
+// configured from the workspace's Anchor.toml.
+
+const anchor = require("@coral-xyz/anchor");
+
+module.exports = async function (provider) {
+  // Configure client to use the provider.
+  anchor.setProvider(provider);
+
+  // Add your deploy script here.
+};

+ 21 - 0
compression/cnft-solang/package.json

@@ -0,0 +1,21 @@
+{
+    "scripts": {
+        "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w",
+        "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check"
+    },
+    "dependencies": {
+        "@coral-xyz/anchor": "^0.28.0",
+        "@metaplex-foundation/mpl-bubblegum": "^0.7.0",
+        "@solana/spl-account-compression": "^0.1.8"
+    },
+    "devDependencies": {
+        "@types/bn.js": "^5.1.0",
+        "@types/chai": "^4.3.0",
+        "@types/mocha": "^9.0.0",
+        "chai": "^4.3.4",
+        "mocha": "^9.0.3",
+        "prettier": "^2.6.2",
+        "ts-mocha": "^10.0.0",
+        "typescript": "^4.3.5"
+    }
+}

+ 144 - 0
compression/cnft-solang/solidity/compressed-nft.sol

@@ -0,0 +1,144 @@
+
+import "solana";
+
+@program_id("BhDH6TLEnf4dLq9hLn2gLwm5rJdj8Cbdc9ZrsjUpL7kB")
+contract compressed_nft {
+
+    @payer(payer) // payer address
+    @seed("seed") // hardcoded seed
+    constructor(
+        @bump bytes1 bump // bump seed for pda address
+    ) {
+        // Creating a dataAccount for the program, which is required by Solang
+        // However, this account is not used in the program
+    }
+
+    // Mint a compressed NFT to an existing merkle tree, via a cross-program invocation to the Bubblegum program
+    // Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/lib.rs#L922
+    // Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/lib.rs#L67
+    function mint(
+        address tree_authority, // authority of the merkle tree
+        address leaf_owner, // owner of the new compressed NFT
+        address leaf_delegate, // delegate of the new compressed NFT (can be the same as leaf_owner)
+        address merkle_tree, // address of the merkle tree
+        address payer, // payer
+        address tree_delegate, // delegate of the merkle tree
+        string uri // uri of the new compressed NFT (metadata)
+    ) public {
+        print("Minting Compressed NFT");
+
+        // Create a creator array with a single creator
+        Creator[] memory creators = new Creator[](1);
+        // Set the creator to the payer
+        creators[0] = Creator({
+            creatorAddress: payer,
+            verified: false,
+            share: 100
+        });
+
+        // Create the metadata args, representing the metadata of the new compressed NFT
+        // Solidity does not support optional arguments,
+        // So we have to explicitly declare if the optional arguments are present or not
+        // If not present, we comment them out, otherwise the transaction will fail with a invalid instruction data error
+        MetadataArgs memory args = MetadataArgs({
+            name: "RGB",
+            symbol: "RGB",
+            uri: uri,
+            sellerFeeBasisPoints: 0,
+            primarySaleHappened: false,
+            isMutable: true,
+            editionNoncePresent: false,
+            // editionNonce: 0,
+            tokenStandardPresent: true,
+            tokenStandard: TokenStandard.NonFungible,
+            collectionPresent: false,
+            // collection: Collection({
+            //     verified: false,
+            //     key: address(0)
+            // }),
+            usesPresent: false,
+            // uses: Uses({
+            //     useMethod: UseMethod.Burn,
+            //     remaining: 0,
+            //     total: 0
+            // }),
+            tokenProgramVersion: TokenProgramVersion.Original,
+            creators: creators
+        });
+
+        AccountMeta[9] metas = [
+            AccountMeta({pubkey: tree_authority, is_writable: true, is_signer: false}),
+            AccountMeta({pubkey: leaf_owner, is_writable: false, is_signer: false}),
+            AccountMeta({pubkey: leaf_delegate, is_writable: false, is_signer: false}),
+            AccountMeta({pubkey: merkle_tree, is_writable: true, is_signer: false}),
+            AccountMeta({pubkey: payer, is_writable: true, is_signer: true}),
+            AccountMeta({pubkey: tree_delegate, is_writable: true, is_signer: true}),
+            AccountMeta({pubkey: address"noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV", is_writable: false, is_signer: false}),
+            AccountMeta({pubkey: address"cmtDvXumGCrqC1Age74AVPhSRVXJMd8PJS91L8KbNCK", is_writable: false, is_signer: false}),
+            AccountMeta({pubkey: address"11111111111111111111111111111111", is_writable: false, is_signer: false})
+        ];
+
+        // Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/js/src/generated/instructions/mintV1.ts#L64
+        bytes8 discriminator = 0x9162c076b8937668;
+        bytes instructionData = abi.encode(discriminator, args);
+
+        // Invoking the Bubblegum program
+        address'BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY'.call{accounts: metas}(instructionData);
+    }
+
+    // Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/state/metaplex_adapter.rs#L81
+    struct MetadataArgs {
+        string name;
+        string symbol;
+        string uri;
+        uint16 sellerFeeBasisPoints;
+        bool primarySaleHappened;
+        bool isMutable;
+        bool editionNoncePresent;
+        // uint8 editionNonce;
+        bool tokenStandardPresent;
+        TokenStandard tokenStandard;
+        bool collectionPresent;
+        // Collection collection;
+        bool usesPresent;
+        // Uses uses;
+        TokenProgramVersion tokenProgramVersion;
+        Creator[] creators;
+    }
+
+    enum TokenStandard {
+        NonFungible,
+        FungibleAsset,
+        Fungible,
+        NonFungibleEdition
+    }
+
+    enum TokenProgramVersion {
+        Original,
+        Token2022
+    }
+
+    struct Creator {
+        address creatorAddress;
+        bool verified;
+        uint8 share;
+    }
+
+    struct Collection {
+        bool verified;
+        address key;
+    }
+
+    struct Uses {
+        UseMethod useMethod;
+        uint64 remaining;
+        uint64 total;
+    }
+
+    enum UseMethod {
+        Burn,
+        Multiple,
+        Single
+    }
+
+}

+ 188 - 0
compression/cnft-solang/tests/compressed-nft.ts

@@ -0,0 +1,188 @@
+import * as anchor from "@coral-xyz/anchor";
+import { Program, Wallet } from "@coral-xyz/anchor";
+import { CompressedNft } from "../target/types/compressed_nft";
+import {
+  PublicKey,
+  SystemProgram,
+  Transaction,
+  Keypair,
+  sendAndConfirmTransaction,
+} from "@solana/web3.js";
+import {
+  SPL_ACCOUNT_COMPRESSION_PROGRAM_ID,
+  ValidDepthSizePair,
+  SPL_NOOP_PROGRAM_ID,
+  createAllocTreeIx,
+} from "@solana/spl-account-compression";
+import {
+  PROGRAM_ID as BUBBLEGUM_PROGRAM_ID,
+  createCreateTreeInstruction,
+} from "@metaplex-foundation/mpl-bubblegum";
+import { uris } from "../utils/uri";
+
+describe("compressed-nft", () => {
+  const provider = anchor.AnchorProvider.env();
+  anchor.setProvider(provider);
+
+  const wallet = provider.wallet as Wallet;
+  const connection = provider.connection;
+
+  const program = anchor.workspace.CompressedNft as Program<CompressedNft>;
+
+  // Generate a new keypair for the merkle tree.
+  const treeKeypair = Keypair.generate();
+
+  // Derive the PDA that will be the tree authority.
+  // This is required by the bubblegum program.
+  const [treeAuthority] = PublicKey.findProgramAddressSync(
+    [treeKeypair.publicKey.toBuffer()],
+    BUBBLEGUM_PROGRAM_ID
+  );
+
+  // Derive the PDA that will be used to initialize the dataAccount.
+  // Required by Solang even though we're not using it.
+  const [dataAccount, bump] = PublicKey.findProgramAddressSync(
+    [Buffer.from("seed")],
+    program.programId
+  );
+
+  // Create a merkle tree account.
+  before(async () => {
+    // Maximum depth and buffer size for the merkle tree.
+    // 2^maxDepth determines the maximum number of leaves that can be stored in the tree.
+    // maxBufferSize determines maximum concurrent updates that can be made within one slot.
+    const maxDepthSizePair: ValidDepthSizePair = {
+      maxDepth: 14,
+      maxBufferSize: 64,
+    };
+
+    // Depth of the canopy (how much of the tree is stored on-chain)
+    const canopyDepth = 0;
+
+    // Instruction to create an account with enough space to store the merkle tree.
+    const allocTreeIx = await createAllocTreeIx(
+      connection,
+      treeKeypair.publicKey,
+      wallet.publicKey,
+      maxDepthSizePair,
+      canopyDepth
+    );
+
+    // Instruction to initialize the merkle tree account with the bubblegum program.
+    const createTreeIx = createCreateTreeInstruction(
+      {
+        treeAuthority,
+        merkleTree: treeKeypair.publicKey,
+        payer: wallet.publicKey,
+        treeCreator: wallet.publicKey,
+        logWrapper: SPL_NOOP_PROGRAM_ID,
+        compressionProgram: SPL_ACCOUNT_COMPRESSION_PROGRAM_ID,
+      },
+      {
+        maxBufferSize: maxDepthSizePair.maxBufferSize,
+        maxDepth: maxDepthSizePair.maxDepth,
+        public: true, // creating a "public" tree, so anyone can mint cnfts to it
+      },
+      BUBBLEGUM_PROGRAM_ID
+    );
+
+    try {
+      const tx = new Transaction().add(allocTreeIx, createTreeIx);
+      tx.feePayer = wallet.publicKey;
+
+      const txSignature = await sendAndConfirmTransaction(
+        connection,
+        tx,
+        [treeKeypair, wallet.payer],
+        {
+          commitment: "confirmed",
+          skipPreflight: true,
+        }
+      );
+
+      console.log(
+        `https://explorer.solana.com/tx/${txSignature}?cluster=devnet`
+      );
+
+      console.log("Tree Address:", treeKeypair.publicKey.toBase58());
+    } catch (err: any) {
+      console.error("\nFailed to create merkle tree:", err);
+      throw err;
+    }
+
+    console.log("\n");
+  });
+
+  it("Is initialized!", async () => {
+    // Initialize the dataAccount.
+    const tx = await program.methods
+      .new([bump])
+      .accounts({ dataAccount: dataAccount })
+      .rpc();
+    console.log("Your transaction signature", tx);
+  });
+
+  it("Mint Compressed NFT", async () => {
+    // Mint a compressed nft to random receiver.
+    const receiver = Keypair.generate().publicKey;
+
+    // Use a random uri (off-chain metadata) from the list for the test.
+    const randomUri = uris[Math.floor(Math.random() * uris.length)];
+
+    const tx = await program.methods
+      .mint(
+        treeAuthority, // treeAuthority
+        receiver, // leafOwner
+        receiver, // leafDelegate
+        treeKeypair.publicKey, // merkleTree
+        wallet.publicKey, // payer
+        wallet.publicKey, // treeDelegate
+        randomUri // uri
+      )
+      .accounts({ dataAccount: dataAccount }) // dataAccount required by Solang even though its unused.
+      .remainingAccounts([
+        {
+          pubkey: wallet.publicKey, // payer (and tree delegate in this example)
+          isWritable: true,
+          isSigner: true,
+        },
+        {
+          pubkey: receiver, // new leaf owner
+          isWritable: false,
+          isSigner: false,
+        },
+        {
+          pubkey: treeAuthority, // tree authority
+          isWritable: true,
+          isSigner: false,
+        },
+        {
+          pubkey: treeKeypair.publicKey, // tree account address
+          isWritable: true,
+          isSigner: false,
+        },
+        {
+          pubkey: SPL_NOOP_PROGRAM_ID,
+          isWritable: false,
+          isSigner: false,
+        },
+        {
+          pubkey: SPL_ACCOUNT_COMPRESSION_PROGRAM_ID,
+          isWritable: false,
+          isSigner: false,
+        },
+        {
+          pubkey: BUBBLEGUM_PROGRAM_ID,
+          isWritable: false,
+          isSigner: false,
+        },
+        {
+          pubkey: SystemProgram.programId,
+          isWritable: false,
+          isSigner: false,
+        },
+      ])
+      .rpc({ skipPreflight: true });
+    console.log("Your transaction signature", tx);
+  });
+});

+ 11 - 0
compression/cnft-solang/tsconfig.json

@@ -0,0 +1,11 @@
+{
+            "compilerOptions": {
+              "types": ["mocha", "chai"],
+              "typeRoots": ["./node_modules/@types"],
+              "lib": ["es2015"],
+              "module": "commonjs",
+              "target": "es6",
+              "esModuleInterop": true
+            }
+          }
+          

+ 12 - 0
compression/cnft-solang/utils/uri.ts

@@ -0,0 +1,12 @@
+export const uris = [
+  "https://raw.githubusercontent.com/ZYJLiu/rgb-png-generator/master/assets/40_183_132/40_183_132.json",
+  "https://raw.githubusercontent.com/ZYJLiu/rgb-png-generator/master/assets/12_217_47/12_217_47.json",
+  "https://raw.githubusercontent.com/ZYJLiu/rgb-png-generator/master/assets/255_68_196/255_68_196.json",
+  "https://raw.githubusercontent.com/ZYJLiu/rgb-png-generator/master/assets/156_61_27/156_61_27.json",
+  "https://raw.githubusercontent.com/ZYJLiu/rgb-png-generator/master/assets/32_150_152/32_150_152.json",
+  "https://raw.githubusercontent.com/ZYJLiu/rgb-png-generator/master/assets/78_96_197/78_96_197.json",
+  "https://raw.githubusercontent.com/ZYJLiu/rgb-png-generator/master/assets/38_47_11/38_47_11.json",
+  "https://raw.githubusercontent.com/ZYJLiu/rgb-png-generator/master/assets/190_85_238/190_85_238.json",
+  "https://raw.githubusercontent.com/ZYJLiu/rgb-png-generator/master/assets/69_46_192/69_46_192.json",
+  "https://raw.githubusercontent.com/ZYJLiu/rgb-png-generator/master/assets/142_17_9/142_17_9.json",
+]

+ 1 - 1
tokens/nft-minter/solang/solidity/mpl_metadata.sol → tokens/create-token/solang/libraries/mpl_metadata.sol

@@ -77,7 +77,7 @@ library MplMetadata {
 		string name,
 		string symbol,
 		string uri
-	) public view {
+	) public {
         // // Example of how to add a Creator[] array to the DataV2 struct
 		// Creator[] memory creators = new Creator[](1);
         // creators[0] = Creator({

+ 10 - 10
tokens/nft-minter/solang/solidity/spl_token.sol → tokens/create-token/solang/libraries/spl_token.sol

@@ -45,7 +45,7 @@ library SplToken {
 	/// @param tokenAccount the public key of the token account to initialize
 	/// @param mint the public key of the mint account for this new token account
 	/// @param owner the public key of the owner of this new token account
-	function initialize_account(address tokenAccount, address mint, address owner) internal view{
+	function initialize_account(address tokenAccount, address mint, address owner) internal{
 		bytes instr = new bytes(1);
 
 		instr[0] = uint8(TokenInstruction.InitializeAccount);
@@ -65,7 +65,7 @@ library SplToken {
 	/// @param tokenAccount the public key of the token account to initialize
 	/// @param mint the public key of the mint account for this new token account
 	/// @param owner the public key of the owner of this new token account
-    function create_associated_token_account(address payer, address tokenAccount, address mint, address owner) internal view {
+    function create_associated_token_account(address payer, address tokenAccount, address mint, address owner) internal {
         AccountMeta[6] metas = [
 			AccountMeta({pubkey: payer, is_writable: true, is_signer: true}),
 			AccountMeta({pubkey: tokenAccount, is_writable: true, is_signer: false}),
@@ -94,7 +94,7 @@ library SplToken {
 	/// @param mintAuthority the public key of the mint authority
 	/// @param freezeAuthority the public key of the freeze authority
 	/// @param decimals the decimals of the mint
-	function initialize_mint(address mint, address mintAuthority, address freezeAuthority, uint8 decimals) internal view {
+	function initialize_mint(address mint, address mintAuthority, address freezeAuthority, uint8 decimals) internal {
     	InitializeMintInstruction instr = InitializeMintInstruction({
             instruction: 20,
             decimals: decimals,
@@ -117,7 +117,7 @@ library SplToken {
 	/// @param mintAuthority the public key of the mint authority
 	/// @param freezeAuthority the public key of the freeze authority
 	/// @param decimals the decimals of the mint
-	function create_mint(address payer, address mint, address mintAuthority, address freezeAuthority, uint8 decimals) internal view {
+	function create_mint(address payer, address mint, address mintAuthority, address freezeAuthority, uint8 decimals) internal {
 		// Invoke System Program to create a new account for the mint account
         // Program owner is set to the Token program
         SystemInstruction.create_account(
@@ -149,7 +149,7 @@ library SplToken {
 	/// @param account the token account where the minted tokens should go
 	/// @param authority the public key of the mint authority
 	/// @param amount the amount of tokens to mint
-	function mint_to(address mint, address account, address authority, uint64 amount) internal view {
+	function mint_to(address mint, address account, address authority, uint64 amount) internal {
 		bytes instr = new bytes(9);
 
 		instr[0] = uint8(TokenInstruction.MintTo);
@@ -171,7 +171,7 @@ library SplToken {
 	/// @param to the account to transfer tokens to
 	/// @param owner the publickey of the from account owner keypair
 	/// @param amount the amount to transfer
-	function transfer(address from, address to, address owner, uint64 amount) internal view {
+	function transfer(address from, address to, address owner, uint64 amount) internal {
 		bytes instr = new bytes(9);
 
 		instr[0] = uint8(TokenInstruction.Transfer);
@@ -192,7 +192,7 @@ library SplToken {
 	/// @param mint the mint for this token
 	/// @param owner the publickey of the account owner keypair
 	/// @param amount the amount to transfer
-	function burn(address account, address mint, address owner, uint64 amount) internal view {
+	function burn(address account, address mint, address owner, uint64 amount) internal {
 		bytes instr = new bytes(9);
 
 		instr[0] = uint8(TokenInstruction.Burn);
@@ -213,7 +213,7 @@ library SplToken {
 	/// @param delegate the delegate publickey
 	/// @param owner the publickey of the account owner keypair
 	/// @param amount the amount to approve
-	function approve(address account, address delegate, address owner, uint64 amount) internal view {
+	function approve(address account, address delegate, address owner, uint64 amount) internal {
 		bytes instr = new bytes(9);
 
 		instr[0] = uint8(TokenInstruction.Approve);
@@ -233,7 +233,7 @@ library SplToken {
 	///
 	/// @param account the account for which a delegate should be approved
 	/// @param owner the publickey of the account owner keypair
-	function revoke(address account, address owner) internal view {
+	function revoke(address account, address owner) internal {
 		bytes instr = new bytes(1);
 
 		instr[0] = uint8(TokenInstruction.Revoke);
@@ -371,7 +371,7 @@ library SplToken {
 	///
 	/// @param mintAccount the public key for the mint account
 	/// @param mintAuthority the public for the mint authority
-	function remove_mint_authority(address mintAccount, address mintAuthority) public view {
+	function remove_mint_authority(address mintAccount, address mintAuthority) public {
 		AccountMeta[2] metas = [
 			AccountMeta({pubkey: mintAccount, is_signer: false, is_writable: true}),
 			AccountMeta({pubkey: mintAuthority, is_signer: true, is_writable: false})

+ 14 - 14
tokens/create-token/solang/solidity/system_instruction.sol → tokens/create-token/solang/libraries/system_instruction.sol

@@ -34,7 +34,7 @@ library SystemInstruction {
     /// @param lamports amount of lamports to be transfered to the new account
     /// @param space the size in bytes that is going to be made available for the account
     /// @param owner public key for the program that will own the account being created
-    function create_account(address from, address to, uint64 lamports, uint64 space, address owner) internal view {
+    function create_account(address from, address to, uint64 lamports, uint64 space, address owner) internal {
         AccountMeta[2] metas = [
             AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
             AccountMeta({pubkey: to, is_signer: true, is_writable: true})
@@ -54,7 +54,7 @@ library SystemInstruction {
     /// @param lamports amount of lamports to be transfered to the new account
     /// @param space the size in bytes that is going to be made available for the account
     /// @param owner public key for the program that will own the account being created
-    function create_account_with_seed(address from, address to, address base, string seed, uint64 lamports, uint64 space, address owner) internal view {
+    function create_account_with_seed(address from, address to, address base, string seed, uint64 lamports, uint64 space, address owner) internal {
         AccountMeta[3] metas = [
             AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
             AccountMeta({pubkey: to, is_signer: false, is_writable: true}),
@@ -81,7 +81,7 @@ library SystemInstruction {
     ///
     /// @param pubkey the public key for the account whose owner is going to be reassigned
     /// @param owner the public key for the new account owner
-    function assign(address pubkey, address owner) internal view {
+    function assign(address pubkey, address owner) internal {
         AccountMeta[1] meta = [
             AccountMeta({pubkey: pubkey, is_signer: true, is_writable: true})
         ];
@@ -96,7 +96,7 @@ library SystemInstruction {
     /// @param base the base address that derived the 'addr' key using the seed
     /// @param seed the string utilized to created the 'addr' public key
     /// @param owner the public key for the new program owner
-    function assign_with_seed(address addr, address base, string seed, address owner) internal view {
+    function assign_with_seed(address addr, address base, string seed, address owner) internal {
         AccountMeta[2] metas = [
             AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: base, is_signer: true, is_writable: false})
@@ -119,7 +119,7 @@ library SystemInstruction {
     /// @param from public key for the funding account
     /// @param to public key for the recipient account
     /// @param lamports amount of lamports to transfer
-    function transfer(address from, address to, uint64 lamports) internal view {
+    function transfer(address from, address to, uint64 lamports) internal {
         AccountMeta[2] metas = [
             AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
             AccountMeta({pubkey: to, is_signer: false, is_writable: true})
@@ -138,7 +138,7 @@ library SystemInstruction {
     /// @param from_owner owner to use to derive the funding account address
     /// @param to_pubkey the public key for the recipient account
     /// @param lamports amount of lamports to transfer
-    function transfer_with_seed(address from_pubkey, address from_base, string seed, address from_owner, address to_pubkey, uint64 lamports) internal view {
+    function transfer_with_seed(address from_pubkey, address from_base, string seed, address from_owner, address to_pubkey, uint64 lamports) internal {
         AccountMeta[3] metas = [
             AccountMeta({pubkey: from_pubkey, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: from_base, is_signer: true, is_writable: false}),
@@ -160,7 +160,7 @@ library SystemInstruction {
     ///
     /// @param pub_key account for which to allocate space
     /// @param space number of bytes of memory to allocate
-    function allocate(address pub_key, uint64 space) internal view {
+    function allocate(address pub_key, uint64 space) internal {
         AccountMeta[1] meta = [
             AccountMeta({pubkey: pub_key, is_signer: true, is_writable: true})
         ];
@@ -177,7 +177,7 @@ library SystemInstruction {
     /// @param seed the string utilized to create the 'addr' public key
     /// @param space number of bytes of memory to allocate
     /// @param owner owner to use to derive the 'addr' account address
-    function allocate_with_seed(address addr, address base, string seed, uint64 space, address owner) internal view {
+    function allocate_with_seed(address addr, address base, string seed, uint64 space, address owner) internal {
         AccountMeta[2] metas = [
             AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: base, is_signer: true, is_writable: false})
@@ -204,7 +204,7 @@ library SystemInstruction {
     /// @param seed the string utilized to create the 'addr' public key
     /// @param authority The entity authorized to execute nonce instructions on the account
     /// @param lamports amount of lamports to be transfered to the new account
-    function create_nonce_account_with_seed(address from, address nonce, address base, string seed, address authority, uint64 lamports) internal view {
+    function create_nonce_account_with_seed(address from, address nonce, address base, string seed, address authority, uint64 lamports) internal {
         create_account_with_seed(from, nonce, base, seed, lamports, state_size, systemAddress);
 
         AccountMeta[3] metas = [
@@ -223,7 +223,7 @@ library SystemInstruction {
     /// @param nonce the public key for the nonce account to be created
     /// @param authority The entity authorized to execute nonce instructions on the account
     /// @param lamports amount of lamports to be transfered to the new account
-    function create_nonce_account(address from, address nonce, address authority, uint64 lamports) internal view {
+    function create_nonce_account(address from, address nonce, address authority, uint64 lamports) internal {
         create_account(from, nonce, lamports, state_size, systemAddress);
 
         AccountMeta[3] metas = [
@@ -240,7 +240,7 @@ library SystemInstruction {
     ///
     /// @param nonce_pubkey the public key for the nonce account
     /// @param authorized_pubkey the publick key for the entity authorized to execute instructins on the account
-    function advance_nonce_account(address nonce_pubkey, address authorized_pubkey) internal view {
+    function advance_nonce_account(address nonce_pubkey, address authorized_pubkey) internal {
         AccountMeta[3] metas = [
             AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
@@ -257,7 +257,7 @@ library SystemInstruction {
     /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
     /// @param to_pubkey the recipient account
     /// @param lamports the number of lamports to withdraw
-    function withdraw_nonce_account(address nonce_pubkey, address authorized_pubkey, address to_pubkey, uint64 lamports) internal view {
+    function withdraw_nonce_account(address nonce_pubkey, address authorized_pubkey, address to_pubkey, uint64 lamports) internal {
         AccountMeta[5] metas = [
             AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: to_pubkey, is_signer: false, is_writable: true}),
@@ -275,7 +275,7 @@ library SystemInstruction {
     /// @param nonce_pubkey the public key for the nonce account
     /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
     /// @param new_authority
-    function authorize_nonce_account(address nonce_pubkey, address authorized_pubkey, address new_authority) internal view {
+    function authorize_nonce_account(address nonce_pubkey, address authorized_pubkey, address new_authority) internal {
         AccountMeta[2] metas = [
             AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
             AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
@@ -289,7 +289,7 @@ library SystemInstruction {
     ///
     /// @param nonce the public key for the nonce account
     // This is not available on Solana v1.9.15
-    function upgrade_nonce_account(address nonce) internal view {
+    function upgrade_nonce_account(address nonce) internal {
         AccountMeta[1] meta = [
             AccountMeta({pubkey: nonce, is_signer: false, is_writable: true})
         ];

+ 2 - 1
tokens/create-token/solang/package.json

@@ -5,7 +5,8 @@
     },
     "dependencies": {
         "@coral-xyz/anchor": "^0.28.0",
-        "@metaplex-foundation/js": "^0.19.4"
+        "@metaplex-foundation/js": "^0.19.4",
+        "@project-serum/anchor": "^0.26.0"
     },
     "devDependencies": {
         "@types/bn.js": "^5.1.0",

+ 4 - 4
tokens/create-token/solang/solidity/create-token.sol

@@ -1,6 +1,6 @@
 
-import "./spl_token.sol";
-import "./mpl_metadata.sol";
+import "../libraries/spl_token.sol";
+import "../libraries/mpl_metadata.sol";
 
 @program_id("8eZPhSaXfHqbcrfskVThtCG68kq8MfVHqmtm6wYf4TLb")
 contract create_token {
@@ -8,7 +8,7 @@ contract create_token {
     // Creating a dataAccount is required by Solang
     // The account is unused in this example
     @payer(payer) // payer account
-    constructor(address payer) {}
+    constructor() {}
 
     function createTokenMint(
         address payer, // payer account
@@ -20,7 +20,7 @@ contract create_token {
         string name, // name for the metadata account
         string symbol, // symbol for the metadata account
         string uri // uri for the metadata account
-    ) public view {
+    ) public {
         // Invoke System Program to create a new account for the mint account and,
         // Invoke Token Program to initialize the mint account
         // Set mint authority, freeze authority, and decimals for the mint account

+ 31 - 31
tokens/create-token/solang/tests/create-token.ts

@@ -1,45 +1,45 @@
-import * as anchor from "@coral-xyz/anchor"
-import { Program } from "@coral-xyz/anchor"
-import { CreateToken } from "../target/types/create_token"
-import { Metaplex } from "@metaplex-foundation/js"
-import { SYSVAR_RENT_PUBKEY, SystemProgram, PublicKey } from "@solana/web3.js"
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { CreateToken } from "../target/types/create_token";
+import { Metaplex } from "@metaplex-foundation/js";
+import { SYSVAR_RENT_PUBKEY, SystemProgram, PublicKey } from "@solana/web3.js";
 
 describe("create-token", () => {
-  const provider = anchor.AnchorProvider.env()
-  anchor.setProvider(provider)
-  const program = anchor.workspace.CreateToken as Program<CreateToken>
+  const provider = anchor.AnchorProvider.env();
+  anchor.setProvider(provider);
+  const program = anchor.workspace.CreateToken as Program<CreateToken>;
 
   // Generate new keypair to use as data account
-  const dataAccount = anchor.web3.Keypair.generate()
-  const wallet = provider.wallet
-  const connection = provider.connection
+  const dataAccount = anchor.web3.Keypair.generate();
+  const wallet = provider.wallet;
+  const connection = provider.connection;
 
   // Metadata for the token
-  const tokenTitle = "Solana Gold"
-  const tokenSymbol = "GOLDSOL"
+  const tokenTitle = "Solana Gold";
+  const tokenSymbol = "GOLDSOL";
   const tokenUri =
-    "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json"
+    "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json";
 
   it("Is initialized!", async () => {
     // Initialize data account for the program, which is required by Solang
     const tx = await program.methods
-      .new(wallet.publicKey)
+      .new()
       .accounts({ dataAccount: dataAccount.publicKey })
       .signers([dataAccount])
-      .rpc()
-    console.log("Your transaction signature", tx)
-  })
+      .rpc();
+    console.log("Your transaction signature", tx);
+  });
 
   it("Create an SPL Token!", async () => {
     // Generate a new keypair for the mint
-    const mintKeypair = anchor.web3.Keypair.generate()
+    const mintKeypair = anchor.web3.Keypair.generate();
 
     // Get the metadata address for the mint
-    const metaplex = Metaplex.make(connection)
+    const metaplex = Metaplex.make(connection);
     const metadataAddress = await metaplex
       .nfts()
       .pdas()
-      .metadata({ mint: mintKeypair.publicKey })
+      .metadata({ mint: mintKeypair.publicKey });
 
     const tx = await program.methods
       .createTokenMint(
@@ -71,20 +71,20 @@ describe("create-token", () => {
         { pubkey: SYSVAR_RENT_PUBKEY, isWritable: false, isSigner: false },
       ])
       .signers([mintKeypair])
-      .rpc({ skipPreflight: true })
-    console.log("Your transaction signature", tx)
-  })
+      .rpc({ skipPreflight: true });
+    console.log("Your transaction signature", tx);
+  });
 
   it("Create an NFT!", async () => {
     // Generate a new keypair for the mint
-    const mintKeypair = anchor.web3.Keypair.generate()
+    const mintKeypair = anchor.web3.Keypair.generate();
 
     // Get the metadata address for the mint
-    const metaplex = Metaplex.make(connection)
+    const metaplex = Metaplex.make(connection);
     const metadataAddress = await metaplex
       .nfts()
       .pdas()
-      .metadata({ mint: mintKeypair.publicKey })
+      .metadata({ mint: mintKeypair.publicKey });
 
     const tx = await program.methods
       .createTokenMint(
@@ -116,7 +116,7 @@ describe("create-token", () => {
         { pubkey: SYSVAR_RENT_PUBKEY, isWritable: false, isSigner: false },
       ])
       .signers([mintKeypair])
-      .rpc({ skipPreflight: true })
-    console.log("Your transaction signature", tx)
-  })
-})
+      .rpc({ skipPreflight: true });
+    console.log("Your transaction signature", tx);
+  });
+});

+ 9 - 9
tokens/create-token/solang/tsconfig.json

@@ -1,11 +1,11 @@
 {
-            "compilerOptions": {
-              "types": ["mocha", "chai"],
-              "typeRoots": ["./node_modules/@types"],
-              "lib": ["es2015"],
-              "module": "commonjs",
-              "target": "es6",
-              "esModuleInterop": true
-            }
-          }
+  "compilerOptions": {
+    "types": ["mocha", "chai"],
+    "typeRoots": ["./node_modules/@types"],
+    "lib": ["es2015"],
+    "module": "commonjs",
+    "target": "es6",
+    "esModuleInterop": true
+  }
+}
           

+ 1 - 1
tokens/pda-mint-authority/solang/solidity/mpl_metadata.sol → tokens/nft-minter/solang/libraries/mpl_metadata.sol

@@ -77,7 +77,7 @@ library MplMetadata {
 		string name,
 		string symbol,
 		string uri
-	) public view {
+	) public {
         // // Example of how to add a Creator[] array to the DataV2 struct
 		// Creator[] memory creators = new Creator[](1);
         // creators[0] = Creator({

+ 10 - 10
tokens/pda-mint-authority/solang/solidity/spl_token.sol → tokens/nft-minter/solang/libraries/spl_token.sol

@@ -45,7 +45,7 @@ library SplToken {
 	/// @param tokenAccount the public key of the token account to initialize
 	/// @param mint the public key of the mint account for this new token account
 	/// @param owner the public key of the owner of this new token account
-	function initialize_account(address tokenAccount, address mint, address owner) internal view{
+	function initialize_account(address tokenAccount, address mint, address owner) internal{
 		bytes instr = new bytes(1);
 
 		instr[0] = uint8(TokenInstruction.InitializeAccount);
@@ -65,7 +65,7 @@ library SplToken {
 	/// @param tokenAccount the public key of the token account to initialize
 	/// @param mint the public key of the mint account for this new token account
 	/// @param owner the public key of the owner of this new token account
-    function create_associated_token_account(address payer, address tokenAccount, address mint, address owner) internal view {
+    function create_associated_token_account(address payer, address tokenAccount, address mint, address owner) internal {
         AccountMeta[6] metas = [
 			AccountMeta({pubkey: payer, is_writable: true, is_signer: true}),
 			AccountMeta({pubkey: tokenAccount, is_writable: true, is_signer: false}),
@@ -94,7 +94,7 @@ library SplToken {
 	/// @param mintAuthority the public key of the mint authority
 	/// @param freezeAuthority the public key of the freeze authority
 	/// @param decimals the decimals of the mint
-	function initialize_mint(address mint, address mintAuthority, address freezeAuthority, uint8 decimals) internal view {
+	function initialize_mint(address mint, address mintAuthority, address freezeAuthority, uint8 decimals) internal {
     	InitializeMintInstruction instr = InitializeMintInstruction({
             instruction: 20,
             decimals: decimals,
@@ -117,7 +117,7 @@ library SplToken {
 	/// @param mintAuthority the public key of the mint authority
 	/// @param freezeAuthority the public key of the freeze authority
 	/// @param decimals the decimals of the mint
-	function create_mint(address payer, address mint, address mintAuthority, address freezeAuthority, uint8 decimals) internal view {
+	function create_mint(address payer, address mint, address mintAuthority, address freezeAuthority, uint8 decimals) internal {
 		// Invoke System Program to create a new account for the mint account
         // Program owner is set to the Token program
         SystemInstruction.create_account(
@@ -149,7 +149,7 @@ library SplToken {
 	/// @param account the token account where the minted tokens should go
 	/// @param authority the public key of the mint authority
 	/// @param amount the amount of tokens to mint
-	function mint_to(address mint, address account, address authority, uint64 amount) internal view {
+	function mint_to(address mint, address account, address authority, uint64 amount) internal {
 		bytes instr = new bytes(9);
 
 		instr[0] = uint8(TokenInstruction.MintTo);
@@ -171,7 +171,7 @@ library SplToken {
 	/// @param to the account to transfer tokens to
 	/// @param owner the publickey of the from account owner keypair
 	/// @param amount the amount to transfer
-	function transfer(address from, address to, address owner, uint64 amount) internal view {
+	function transfer(address from, address to, address owner, uint64 amount) internal {
 		bytes instr = new bytes(9);
 
 		instr[0] = uint8(TokenInstruction.Transfer);
@@ -192,7 +192,7 @@ library SplToken {
 	/// @param mint the mint for this token
 	/// @param owner the publickey of the account owner keypair
 	/// @param amount the amount to transfer
-	function burn(address account, address mint, address owner, uint64 amount) internal view {
+	function burn(address account, address mint, address owner, uint64 amount) internal {
 		bytes instr = new bytes(9);
 
 		instr[0] = uint8(TokenInstruction.Burn);
@@ -213,7 +213,7 @@ library SplToken {
 	/// @param delegate the delegate publickey
 	/// @param owner the publickey of the account owner keypair
 	/// @param amount the amount to approve
-	function approve(address account, address delegate, address owner, uint64 amount) internal view {
+	function approve(address account, address delegate, address owner, uint64 amount) internal {
 		bytes instr = new bytes(9);
 
 		instr[0] = uint8(TokenInstruction.Approve);
@@ -233,7 +233,7 @@ library SplToken {
 	///
 	/// @param account the account for which a delegate should be approved
 	/// @param owner the publickey of the account owner keypair
-	function revoke(address account, address owner) internal view {
+	function revoke(address account, address owner) internal {
 		bytes instr = new bytes(1);
 
 		instr[0] = uint8(TokenInstruction.Revoke);
@@ -371,7 +371,7 @@ library SplToken {
 	///
 	/// @param mintAccount the public key for the mint account
 	/// @param mintAuthority the public for the mint authority
-	function remove_mint_authority(address mintAccount, address mintAuthority) public view {
+	function remove_mint_authority(address mintAccount, address mintAuthority) public {
 		AccountMeta[2] metas = [
 			AccountMeta({pubkey: mintAccount, is_signer: false, is_writable: true}),
 			AccountMeta({pubkey: mintAuthority, is_signer: true, is_writable: false})

+ 300 - 0
tokens/nft-minter/solang/libraries/system_instruction.sol

@@ -0,0 +1,300 @@
+// SPDX-License-Identifier: Apache-2.0
+
+// Disclaimer: This library provides a bridge for Solidity to interact with Solana's system instructions. Although it is production ready,
+// it has not been audited for security, so use it at your own risk.
+
+import 'solana';
+
+library SystemInstruction {
+    address constant systemAddress = address"11111111111111111111111111111111";
+    address constant recentBlockHashes = address"SysvarRecentB1ockHashes11111111111111111111";
+    address constant rentAddress = address"SysvarRent111111111111111111111111111111111";
+    uint64 constant state_size = 80;
+
+    enum Instruction {
+        CreateAccount,
+        Assign,
+        Transfer,
+        CreateAccountWithSeed,
+        AdvanceNounceAccount,
+        WithdrawNonceAccount,
+        InitializeNonceAccount,
+        AuthorizeNonceAccount,
+        Allocate,
+        AllocateWithSeed,
+        AssignWithSeed,
+        TransferWithSeed,
+        UpgradeNonceAccount // This is not available on Solana v1.9.15
+    }
+
+    /// Create a new account on Solana
+    ///
+    /// @param from public key for the account from which to transfer lamports to the new account
+    /// @param to public key for the account to be created
+    /// @param lamports amount of lamports to be transfered to the new account
+    /// @param space the size in bytes that is going to be made available for the account
+    /// @param owner public key for the program that will own the account being created
+    function create_account(address from, address to, uint64 lamports, uint64 space, address owner) internal {
+        AccountMeta[2] metas = [
+            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
+            AccountMeta({pubkey: to, is_signer: true, is_writable: true})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.CreateAccount), lamports, space, owner);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Create a new account on Solana using a public key derived from a seed
+    ///
+    /// @param from public key for the account from which to transfer lamports to the new account
+    /// @param to the public key for the account to be created. The public key must match create_with_seed(base, seed, owner)
+    /// @param base the base address that derived the 'to' address using the seed
+    /// @param seed the string utilized to created the 'to' public key
+    /// @param lamports amount of lamports to be transfered to the new account
+    /// @param space the size in bytes that is going to be made available for the account
+    /// @param owner public key for the program that will own the account being created
+    function create_account_with_seed(address from, address to, address base, string seed, uint64 lamports, uint64 space, address owner) internal {
+        AccountMeta[3] metas = [
+            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
+            AccountMeta({pubkey: to, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
+        ];
+
+        uint32 buffer_size = 92 + seed.length;
+        bytes bincode = new bytes(buffer_size);
+        bincode.writeUint32LE(uint32(Instruction.CreateAccountWithSeed), 0);
+        bincode.writeAddress(base, 4);
+        bincode.writeUint64LE(uint64(seed.length), 36);
+        bincode.writeString(seed, 44);
+        uint32 offset = seed.length + 44;
+        bincode.writeUint64LE(lamports, offset);
+        offset += 8;
+        bincode.writeUint64LE(space, offset);
+        offset += 8;
+        bincode.writeAddress(owner, offset);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Assign account to a program (owner)
+    ///
+    /// @param pubkey the public key for the account whose owner is going to be reassigned
+    /// @param owner the public key for the new account owner
+    function assign(address pubkey, address owner) internal {
+        AccountMeta[1] meta = [
+            AccountMeta({pubkey: pubkey, is_signer: true, is_writable: true})
+        ];
+        bytes bincode = abi.encode(uint32(Instruction.Assign), owner);
+
+        systemAddress.call{accounts: meta}(bincode);
+    }
+
+    /// Assign account to a program (owner) based on a seed
+    ///
+    /// @param addr the public key for the account whose owner is going to be reassigned. The public key must match create_with_seed(base, seed, owner)
+    /// @param base the base address that derived the 'addr' key using the seed
+    /// @param seed the string utilized to created the 'addr' public key
+    /// @param owner the public key for the new program owner
+    function assign_with_seed(address addr, address base, string seed, address owner) internal {
+        AccountMeta[2] metas = [
+            AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
+        ];
+
+
+        uint32 buffer_size = 76 + seed.length;
+        bytes bincode = new bytes(buffer_size);
+        bincode.writeUint32LE(uint32(Instruction.AssignWithSeed), 0);
+        bincode.writeAddress(base, 4);
+        bincode.writeUint64LE(uint64(seed.length), 36);
+        bincode.writeString(seed, 44);
+        bincode.writeAddress(owner, 44 + seed.length);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Transfer lamports between accounts
+    ///
+    /// @param from public key for the funding account
+    /// @param to public key for the recipient account
+    /// @param lamports amount of lamports to transfer
+    function transfer(address from, address to, uint64 lamports) internal {
+        AccountMeta[2] metas = [
+            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
+            AccountMeta({pubkey: to, is_signer: false, is_writable: true})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.Transfer), lamports);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Transfer lamports from a derived address
+    ///
+    /// @param from_pubkey The funding account public key. It should match create_with_seed(from_base, seed, from_owner)
+    /// @param from_base the base address that derived the 'from_pubkey' key using the seed
+    /// @param seed the string utilized to create the 'from_pubkey' public key
+    /// @param from_owner owner to use to derive the funding account address
+    /// @param to_pubkey the public key for the recipient account
+    /// @param lamports amount of lamports to transfer
+    function transfer_with_seed(address from_pubkey, address from_base, string seed, address from_owner, address to_pubkey, uint64 lamports) internal {
+        AccountMeta[3] metas = [
+            AccountMeta({pubkey: from_pubkey, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: from_base, is_signer: true, is_writable: false}),
+            AccountMeta({pubkey: to_pubkey, is_signer: false, is_writable: true})
+        ];
+
+        uint32 buffer_size = seed.length + 52;
+        bytes bincode = new bytes(buffer_size);
+        bincode.writeUint32LE(uint32(Instruction.TransferWithSeed), 0);
+        bincode.writeUint64LE(lamports, 4);
+        bincode.writeUint64LE(seed.length, 12);
+        bincode.writeString(seed, 20);
+        bincode.writeAddress(from_owner, 20 + seed.length);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Allocate space in a (possibly new) account without funding
+    ///
+    /// @param pub_key account for which to allocate space
+    /// @param space number of bytes of memory to allocate
+    function allocate(address pub_key, uint64 space) internal {
+        AccountMeta[1] meta = [
+            AccountMeta({pubkey: pub_key, is_signer: true, is_writable: true})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.Allocate), space);
+
+        systemAddress.call{accounts: meta}(bincode);
+    }
+
+    /// Allocate space for an assign an account at an address derived from a base public key and a seed
+    ///
+    /// @param addr account for which to allocate space. It should match create_with_seed(base, seed, owner)
+    /// @param base the base address that derived the 'addr' key using the seed
+    /// @param seed the string utilized to create the 'addr' public key
+    /// @param space number of bytes of memory to allocate
+    /// @param owner owner to use to derive the 'addr' account address
+    function allocate_with_seed(address addr, address base, string seed, uint64 space, address owner) internal {
+        AccountMeta[2] metas = [
+            AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
+        ];
+
+        bytes bincode = new bytes(seed.length + 84);
+        bincode.writeUint32LE(uint32(Instruction.AllocateWithSeed), 0);
+        bincode.writeAddress(base, 4);
+        bincode.writeUint64LE(seed.length, 36);
+        bincode.writeString(seed, 44);
+        uint32 offset = 44 + seed.length;
+        bincode.writeUint64LE(space, offset);
+        offset += 8;
+        bincode.writeAddress(owner, offset);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Create a new nonce account on Solana using a public key derived from a seed
+    ///
+    /// @param from public key for the account from which to transfer lamports to the new account
+    /// @param nonce the public key for the account to be created. The public key must match create_with_seed(base, seed, systemAddress)
+    /// @param base the base address that derived the 'nonce' key using the seed
+    /// @param seed the string utilized to create the 'addr' public key
+    /// @param authority The entity authorized to execute nonce instructions on the account
+    /// @param lamports amount of lamports to be transfered to the new account
+    function create_nonce_account_with_seed(address from, address nonce, address base, string seed, address authority, uint64 lamports) internal {
+        create_account_with_seed(from, nonce, base, seed, lamports, state_size, systemAddress);
+
+        AccountMeta[3] metas = [
+            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
+            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.InitializeNonceAccount), authority);
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Create a new account on Solana
+    ///
+    /// @param from public key for the account from which to transfer lamports to the new account
+    /// @param nonce the public key for the nonce account to be created
+    /// @param authority The entity authorized to execute nonce instructions on the account
+    /// @param lamports amount of lamports to be transfered to the new account
+    function create_nonce_account(address from, address nonce, address authority, uint64 lamports) internal {
+        create_account(from, nonce, lamports, state_size, systemAddress);
+
+        AccountMeta[3] metas = [
+            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
+            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.InitializeNonceAccount), authority);
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Consumes a stored nonce, replacing it with a successor
+    ///
+    /// @param nonce_pubkey the public key for the nonce account
+    /// @param authorized_pubkey the publick key for the entity authorized to execute instructins on the account
+    function advance_nonce_account(address nonce_pubkey, address authorized_pubkey) internal {
+        AccountMeta[3] metas = [
+            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
+            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.AdvanceNounceAccount));
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Withdraw funds from a nonce account
+    ///
+    /// @param nonce_pubkey the public key for the nonce account
+    /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
+    /// @param to_pubkey the recipient account
+    /// @param lamports the number of lamports to withdraw
+    function withdraw_nonce_account(address nonce_pubkey, address authorized_pubkey, address to_pubkey, uint64 lamports) internal {
+        AccountMeta[5] metas = [
+            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: to_pubkey, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
+            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false}),
+            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.WithdrawNonceAccount), lamports);
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Change the entity authorized to execute nonce instructions on the account
+    ///
+    /// @param nonce_pubkey the public key for the nonce account
+    /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
+    /// @param new_authority
+    function authorize_nonce_account(address nonce_pubkey, address authorized_pubkey, address new_authority) internal {
+        AccountMeta[2] metas = [
+            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.AuthorizeNonceAccount), new_authority);
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// One-time idempotent upgrade of legacy nonce version in order to bump them out of chain domain.
+    ///
+    /// @param nonce the public key for the nonce account
+    // This is not available on Solana v1.9.15
+    function upgrade_nonce_account(address nonce) internal {
+        AccountMeta[1] meta = [
+            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.UpgradeNonceAccount));
+        systemAddress.call{accounts: meta}(bincode);
+    }
+}

+ 1 - 0
tokens/nft-minter/solang/package.json

@@ -6,6 +6,7 @@
     "dependencies": {
         "@coral-xyz/anchor": "^0.28.0",
         "@metaplex-foundation/js": "^0.19.4",
+        "@project-serum/anchor": "^0.26.0",
         "@solana/spl-token": "^0.3.8"
     },
     "devDependencies": {

+ 5 - 5
tokens/nft-minter/solang/solidity/nft-minter.sol

@@ -1,12 +1,12 @@
 
-import "./spl_token.sol";
-import "./mpl_metadata.sol";
+import "../libraries/spl_token.sol";
+import "../libraries/mpl_metadata.sol";
 
 @program_id("F1ipperKF9EfD821ZbbYjS319LXYiBmjhzkkf5a26rC")
 contract nft_minter {
 
     @payer(payer)
-    constructor(address payer) {}
+    constructor() {}
 
     function createTokenMint(
         address payer, // payer account
@@ -18,7 +18,7 @@ contract nft_minter {
         string name, // name for the metadata account
         string symbol, // symbol for the metadata account
         string uri // uri for the metadata account
-    ) public view {
+    ) public {
         // Invoke System Program to create a new account for the mint account and,
         // Invoke Token Program to initialize the mint account
         // Set mint authority, freeze authority, and decimals for the mint account
@@ -43,7 +43,7 @@ contract nft_minter {
         );
     }
 
-    function mintTo(address payer, address tokenAccount, address mint, address owner) public view {
+    function mintTo(address payer, address tokenAccount, address mint, address owner) public {
         // Create an associated token account for the owner to receive the minted token
         SplToken.create_associated_token_account(
             payer, // payer account

+ 0 - 300
tokens/nft-minter/solang/solidity/system_instruction.sol

@@ -1,300 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-// Disclaimer: This library provides a bridge for Solidity to interact with Solana's system instructions. Although it is production ready,
-// it has not been audited for security, so use it at your own risk.
-
-import 'solana';
-
-library SystemInstruction {
-    address constant systemAddress = address"11111111111111111111111111111111";
-    address constant recentBlockHashes = address"SysvarRecentB1ockHashes11111111111111111111";
-    address constant rentAddress = address"SysvarRent111111111111111111111111111111111";
-    uint64 constant state_size = 80;
-
-    enum Instruction {
-        CreateAccount,
-        Assign,
-        Transfer,
-        CreateAccountWithSeed,
-        AdvanceNounceAccount,
-        WithdrawNonceAccount,
-        InitializeNonceAccount,
-        AuthorizeNonceAccount,
-        Allocate,
-        AllocateWithSeed,
-        AssignWithSeed,
-        TransferWithSeed,
-        UpgradeNonceAccount // This is not available on Solana v1.9.15
-    }
-
-    /// Create a new account on Solana
-    ///
-    /// @param from public key for the account from which to transfer lamports to the new account
-    /// @param to public key for the account to be created
-    /// @param lamports amount of lamports to be transfered to the new account
-    /// @param space the size in bytes that is going to be made available for the account
-    /// @param owner public key for the program that will own the account being created
-    function create_account(address from, address to, uint64 lamports, uint64 space, address owner) internal view {
-        AccountMeta[2] metas = [
-            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
-            AccountMeta({pubkey: to, is_signer: true, is_writable: true})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.CreateAccount), lamports, space, owner);
-
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Create a new account on Solana using a public key derived from a seed
-    ///
-    /// @param from public key for the account from which to transfer lamports to the new account
-    /// @param to the public key for the account to be created. The public key must match create_with_seed(base, seed, owner)
-    /// @param base the base address that derived the 'to' address using the seed
-    /// @param seed the string utilized to created the 'to' public key
-    /// @param lamports amount of lamports to be transfered to the new account
-    /// @param space the size in bytes that is going to be made available for the account
-    /// @param owner public key for the program that will own the account being created
-    function create_account_with_seed(address from, address to, address base, string seed, uint64 lamports, uint64 space, address owner) internal view {
-        AccountMeta[3] metas = [
-            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
-            AccountMeta({pubkey: to, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
-        ];
-
-        uint32 buffer_size = 92 + seed.length;
-        bytes bincode = new bytes(buffer_size);
-        bincode.writeUint32LE(uint32(Instruction.CreateAccountWithSeed), 0);
-        bincode.writeAddress(base, 4);
-        bincode.writeUint64LE(uint64(seed.length), 36);
-        bincode.writeString(seed, 44);
-        uint32 offset = seed.length + 44;
-        bincode.writeUint64LE(lamports, offset);
-        offset += 8;
-        bincode.writeUint64LE(space, offset);
-        offset += 8;
-        bincode.writeAddress(owner, offset);
-
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Assign account to a program (owner)
-    ///
-    /// @param pubkey the public key for the account whose owner is going to be reassigned
-    /// @param owner the public key for the new account owner
-    function assign(address pubkey, address owner) internal view {
-        AccountMeta[1] meta = [
-            AccountMeta({pubkey: pubkey, is_signer: true, is_writable: true})
-        ];
-        bytes bincode = abi.encode(uint32(Instruction.Assign), owner);
-
-        systemAddress.call{accounts: meta}(bincode);
-    }
-
-    /// Assign account to a program (owner) based on a seed
-    ///
-    /// @param addr the public key for the account whose owner is going to be reassigned. The public key must match create_with_seed(base, seed, owner)
-    /// @param base the base address that derived the 'addr' key using the seed
-    /// @param seed the string utilized to created the 'addr' public key
-    /// @param owner the public key for the new program owner
-    function assign_with_seed(address addr, address base, string seed, address owner) internal view {
-        AccountMeta[2] metas = [
-            AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
-        ];
-
-
-        uint32 buffer_size = 76 + seed.length;
-        bytes bincode = new bytes(buffer_size);
-        bincode.writeUint32LE(uint32(Instruction.AssignWithSeed), 0);
-        bincode.writeAddress(base, 4);
-        bincode.writeUint64LE(uint64(seed.length), 36);
-        bincode.writeString(seed, 44);
-        bincode.writeAddress(owner, 44 + seed.length);
-
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Transfer lamports between accounts
-    ///
-    /// @param from public key for the funding account
-    /// @param to public key for the recipient account
-    /// @param lamports amount of lamports to transfer
-    function transfer(address from, address to, uint64 lamports) internal view {
-        AccountMeta[2] metas = [
-            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
-            AccountMeta({pubkey: to, is_signer: false, is_writable: true})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.Transfer), lamports);
-
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Transfer lamports from a derived address
-    ///
-    /// @param from_pubkey The funding account public key. It should match create_with_seed(from_base, seed, from_owner)
-    /// @param from_base the base address that derived the 'from_pubkey' key using the seed
-    /// @param seed the string utilized to create the 'from_pubkey' public key
-    /// @param from_owner owner to use to derive the funding account address
-    /// @param to_pubkey the public key for the recipient account
-    /// @param lamports amount of lamports to transfer
-    function transfer_with_seed(address from_pubkey, address from_base, string seed, address from_owner, address to_pubkey, uint64 lamports) internal view {
-        AccountMeta[3] metas = [
-            AccountMeta({pubkey: from_pubkey, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: from_base, is_signer: true, is_writable: false}),
-            AccountMeta({pubkey: to_pubkey, is_signer: false, is_writable: true})
-        ];
-
-        uint32 buffer_size = seed.length + 52;
-        bytes bincode = new bytes(buffer_size);
-        bincode.writeUint32LE(uint32(Instruction.TransferWithSeed), 0);
-        bincode.writeUint64LE(lamports, 4);
-        bincode.writeUint64LE(seed.length, 12);
-        bincode.writeString(seed, 20);
-        bincode.writeAddress(from_owner, 20 + seed.length);
-
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Allocate space in a (possibly new) account without funding
-    ///
-    /// @param pub_key account for which to allocate space
-    /// @param space number of bytes of memory to allocate
-    function allocate(address pub_key, uint64 space) internal view {
-        AccountMeta[1] meta = [
-            AccountMeta({pubkey: pub_key, is_signer: true, is_writable: true})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.Allocate), space);
-
-        systemAddress.call{accounts: meta}(bincode);
-    }
-
-    /// Allocate space for an assign an account at an address derived from a base public key and a seed
-    ///
-    /// @param addr account for which to allocate space. It should match create_with_seed(base, seed, owner)
-    /// @param base the base address that derived the 'addr' key using the seed
-    /// @param seed the string utilized to create the 'addr' public key
-    /// @param space number of bytes of memory to allocate
-    /// @param owner owner to use to derive the 'addr' account address
-    function allocate_with_seed(address addr, address base, string seed, uint64 space, address owner) internal view {
-        AccountMeta[2] metas = [
-            AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
-        ];
-
-        bytes bincode = new bytes(seed.length + 84);
-        bincode.writeUint32LE(uint32(Instruction.AllocateWithSeed), 0);
-        bincode.writeAddress(base, 4);
-        bincode.writeUint64LE(seed.length, 36);
-        bincode.writeString(seed, 44);
-        uint32 offset = 44 + seed.length;
-        bincode.writeUint64LE(space, offset);
-        offset += 8;
-        bincode.writeAddress(owner, offset);
-
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Create a new nonce account on Solana using a public key derived from a seed
-    ///
-    /// @param from public key for the account from which to transfer lamports to the new account
-    /// @param nonce the public key for the account to be created. The public key must match create_with_seed(base, seed, systemAddress)
-    /// @param base the base address that derived the 'nonce' key using the seed
-    /// @param seed the string utilized to create the 'addr' public key
-    /// @param authority The entity authorized to execute nonce instructions on the account
-    /// @param lamports amount of lamports to be transfered to the new account
-    function create_nonce_account_with_seed(address from, address nonce, address base, string seed, address authority, uint64 lamports) internal view {
-        create_account_with_seed(from, nonce, base, seed, lamports, state_size, systemAddress);
-
-        AccountMeta[3] metas = [
-            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
-            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.InitializeNonceAccount), authority);
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Create a new account on Solana
-    ///
-    /// @param from public key for the account from which to transfer lamports to the new account
-    /// @param nonce the public key for the nonce account to be created
-    /// @param authority The entity authorized to execute nonce instructions on the account
-    /// @param lamports amount of lamports to be transfered to the new account
-    function create_nonce_account(address from, address nonce, address authority, uint64 lamports) internal view {
-        create_account(from, nonce, lamports, state_size, systemAddress);
-
-        AccountMeta[3] metas = [
-            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
-            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.InitializeNonceAccount), authority);
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Consumes a stored nonce, replacing it with a successor
-    ///
-    /// @param nonce_pubkey the public key for the nonce account
-    /// @param authorized_pubkey the publick key for the entity authorized to execute instructins on the account
-    function advance_nonce_account(address nonce_pubkey, address authorized_pubkey) internal view {
-        AccountMeta[3] metas = [
-            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
-            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.AdvanceNounceAccount));
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Withdraw funds from a nonce account
-    ///
-    /// @param nonce_pubkey the public key for the nonce account
-    /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
-    /// @param to_pubkey the recipient account
-    /// @param lamports the number of lamports to withdraw
-    function withdraw_nonce_account(address nonce_pubkey, address authorized_pubkey, address to_pubkey, uint64 lamports) internal view {
-        AccountMeta[5] metas = [
-            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: to_pubkey, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
-            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false}),
-            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.WithdrawNonceAccount), lamports);
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Change the entity authorized to execute nonce instructions on the account
-    ///
-    /// @param nonce_pubkey the public key for the nonce account
-    /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
-    /// @param new_authority
-    function authorize_nonce_account(address nonce_pubkey, address authorized_pubkey, address new_authority) internal view {
-        AccountMeta[2] metas = [
-            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.AuthorizeNonceAccount), new_authority);
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// One-time idempotent upgrade of legacy nonce version in order to bump them out of chain domain.
-    ///
-    /// @param nonce the public key for the nonce account
-    // This is not available on Solana v1.9.15
-    function upgrade_nonce_account(address nonce) internal view {
-        AccountMeta[1] meta = [
-            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.UpgradeNonceAccount));
-        systemAddress.call{accounts: meta}(bincode);
-    }
-}

+ 30 - 30
tokens/nft-minter/solang/tests/nft-minter.ts

@@ -1,52 +1,52 @@
-import * as anchor from "@coral-xyz/anchor"
-import { Program } from "@coral-xyz/anchor"
-import { NftMinter } from "../target/types/nft_minter"
-import { PublicKey, SystemProgram, SYSVAR_RENT_PUBKEY } from "@solana/web3.js"
-import { Metaplex } from "@metaplex-foundation/js"
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { NftMinter } from "../target/types/nft_minter";
+import { PublicKey, SystemProgram, SYSVAR_RENT_PUBKEY } from "@solana/web3.js";
+import { Metaplex } from "@metaplex-foundation/js";
 import {
   ASSOCIATED_TOKEN_PROGRAM_ID,
   getAssociatedTokenAddressSync,
   TOKEN_PROGRAM_ID,
-} from "@solana/spl-token"
+} from "@solana/spl-token";
 
 describe("nft-minter", () => {
   // Configure the client to use the local cluster.
-  const provider = anchor.AnchorProvider.env()
-  anchor.setProvider(provider)
+  const provider = anchor.AnchorProvider.env();
+  anchor.setProvider(provider);
 
   // Generate a new keypair for the data account for the program
-  const dataAccount = anchor.web3.Keypair.generate()
+  const dataAccount = anchor.web3.Keypair.generate();
 
   // Generate a mint keypair
-  const mintKeypair = anchor.web3.Keypair.generate()
-  const wallet = provider.wallet
-  const connection = provider.connection
+  const mintKeypair = anchor.web3.Keypair.generate();
+  const wallet = provider.wallet;
+  const connection = provider.connection;
 
-  const program = anchor.workspace.NftMinter as Program<NftMinter>
+  const program = anchor.workspace.NftMinter as Program<NftMinter>;
 
   // Metadata for the NFT
-  const nftTitle = "Homer NFT"
-  const nftSymbol = "HOMR"
+  const nftTitle = "Homer NFT";
+  const nftSymbol = "HOMR";
   const nftUri =
-    "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/nft.json"
+    "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/nft.json";
 
   it("Is initialized!", async () => {
     // Initialize data account for the program, which is required by Solang
     const tx = await program.methods
-      .new(wallet.publicKey)
+      .new()
       .accounts({ dataAccount: dataAccount.publicKey })
       .signers([dataAccount])
-      .rpc()
-    console.log("Your transaction signature", tx)
-  })
+      .rpc();
+    console.log("Your transaction signature", tx);
+  });
 
   it("Create an NFT!", async () => {
     // Get the metadata address for the mint
-    const metaplex = Metaplex.make(connection)
+    const metaplex = Metaplex.make(connection);
     const metadataAddress = await metaplex
       .nfts()
       .pdas()
-      .metadata({ mint: mintKeypair.publicKey })
+      .metadata({ mint: mintKeypair.publicKey });
 
     const tx = await program.methods
       .createTokenMint(
@@ -78,16 +78,16 @@ describe("nft-minter", () => {
         { pubkey: SYSVAR_RENT_PUBKEY, isWritable: false, isSigner: false },
       ])
       .signers([mintKeypair])
-      .rpc({ skipPreflight: true })
-    console.log("Your transaction signature", tx)
-  })
+      .rpc({ skipPreflight: true });
+    console.log("Your transaction signature", tx);
+  });
 
   it("Mint the NFT to your wallet!", async () => {
     // Derive wallet's associated token account address for mint
     const tokenAccount = getAssociatedTokenAddressSync(
       mintKeypair.publicKey,
       wallet.publicKey
-    )
+    );
 
     const tx = await program.methods
       .mintTo(
@@ -117,7 +117,7 @@ describe("nft-minter", () => {
           isSigner: false,
         },
       ])
-      .rpc({ skipPreflight: true })
-    console.log("Your transaction signature", tx)
-  })
-})
+      .rpc({ skipPreflight: true });
+    console.log("Your transaction signature", tx);
+  });
+});

+ 1 - 1
tokens/spl-token-minter/solang/solidity/mpl_metadata.sol → tokens/pda-mint-authority/solang/libraries/mpl_metadata.sol

@@ -77,7 +77,7 @@ library MplMetadata {
 		string name,
 		string symbol,
 		string uri
-	) public view {
+	) public {
         // // Example of how to add a Creator[] array to the DataV2 struct
 		// Creator[] memory creators = new Creator[](1);
         // creators[0] = Creator({

+ 10 - 10
tokens/spl-token-minter/solang/solidity/spl_token.sol → tokens/pda-mint-authority/solang/libraries/spl_token.sol

@@ -45,7 +45,7 @@ library SplToken {
 	/// @param tokenAccount the public key of the token account to initialize
 	/// @param mint the public key of the mint account for this new token account
 	/// @param owner the public key of the owner of this new token account
-	function initialize_account(address tokenAccount, address mint, address owner) internal view{
+	function initialize_account(address tokenAccount, address mint, address owner) internal{
 		bytes instr = new bytes(1);
 
 		instr[0] = uint8(TokenInstruction.InitializeAccount);
@@ -65,7 +65,7 @@ library SplToken {
 	/// @param tokenAccount the public key of the token account to initialize
 	/// @param mint the public key of the mint account for this new token account
 	/// @param owner the public key of the owner of this new token account
-    function create_associated_token_account(address payer, address tokenAccount, address mint, address owner) internal view {
+    function create_associated_token_account(address payer, address tokenAccount, address mint, address owner) internal {
         AccountMeta[6] metas = [
 			AccountMeta({pubkey: payer, is_writable: true, is_signer: true}),
 			AccountMeta({pubkey: tokenAccount, is_writable: true, is_signer: false}),
@@ -94,7 +94,7 @@ library SplToken {
 	/// @param mintAuthority the public key of the mint authority
 	/// @param freezeAuthority the public key of the freeze authority
 	/// @param decimals the decimals of the mint
-	function initialize_mint(address mint, address mintAuthority, address freezeAuthority, uint8 decimals) internal view {
+	function initialize_mint(address mint, address mintAuthority, address freezeAuthority, uint8 decimals) internal {
     	InitializeMintInstruction instr = InitializeMintInstruction({
             instruction: 20,
             decimals: decimals,
@@ -117,7 +117,7 @@ library SplToken {
 	/// @param mintAuthority the public key of the mint authority
 	/// @param freezeAuthority the public key of the freeze authority
 	/// @param decimals the decimals of the mint
-	function create_mint(address payer, address mint, address mintAuthority, address freezeAuthority, uint8 decimals) internal view {
+	function create_mint(address payer, address mint, address mintAuthority, address freezeAuthority, uint8 decimals) internal {
 		// Invoke System Program to create a new account for the mint account
         // Program owner is set to the Token program
         SystemInstruction.create_account(
@@ -149,7 +149,7 @@ library SplToken {
 	/// @param account the token account where the minted tokens should go
 	/// @param authority the public key of the mint authority
 	/// @param amount the amount of tokens to mint
-	function mint_to(address mint, address account, address authority, uint64 amount) internal view {
+	function mint_to(address mint, address account, address authority, uint64 amount) internal {
 		bytes instr = new bytes(9);
 
 		instr[0] = uint8(TokenInstruction.MintTo);
@@ -171,7 +171,7 @@ library SplToken {
 	/// @param to the account to transfer tokens to
 	/// @param owner the publickey of the from account owner keypair
 	/// @param amount the amount to transfer
-	function transfer(address from, address to, address owner, uint64 amount) internal view {
+	function transfer(address from, address to, address owner, uint64 amount) internal {
 		bytes instr = new bytes(9);
 
 		instr[0] = uint8(TokenInstruction.Transfer);
@@ -192,7 +192,7 @@ library SplToken {
 	/// @param mint the mint for this token
 	/// @param owner the publickey of the account owner keypair
 	/// @param amount the amount to transfer
-	function burn(address account, address mint, address owner, uint64 amount) internal view {
+	function burn(address account, address mint, address owner, uint64 amount) internal {
 		bytes instr = new bytes(9);
 
 		instr[0] = uint8(TokenInstruction.Burn);
@@ -213,7 +213,7 @@ library SplToken {
 	/// @param delegate the delegate publickey
 	/// @param owner the publickey of the account owner keypair
 	/// @param amount the amount to approve
-	function approve(address account, address delegate, address owner, uint64 amount) internal view {
+	function approve(address account, address delegate, address owner, uint64 amount) internal {
 		bytes instr = new bytes(9);
 
 		instr[0] = uint8(TokenInstruction.Approve);
@@ -233,7 +233,7 @@ library SplToken {
 	///
 	/// @param account the account for which a delegate should be approved
 	/// @param owner the publickey of the account owner keypair
-	function revoke(address account, address owner) internal view {
+	function revoke(address account, address owner) internal {
 		bytes instr = new bytes(1);
 
 		instr[0] = uint8(TokenInstruction.Revoke);
@@ -371,7 +371,7 @@ library SplToken {
 	///
 	/// @param mintAccount the public key for the mint account
 	/// @param mintAuthority the public for the mint authority
-	function remove_mint_authority(address mintAccount, address mintAuthority) public view {
+	function remove_mint_authority(address mintAccount, address mintAuthority) public {
 		AccountMeta[2] metas = [
 			AccountMeta({pubkey: mintAccount, is_signer: false, is_writable: true}),
 			AccountMeta({pubkey: mintAuthority, is_signer: true, is_writable: false})

+ 300 - 0
tokens/pda-mint-authority/solang/libraries/system_instruction.sol

@@ -0,0 +1,300 @@
+// SPDX-License-Identifier: Apache-2.0
+
+// Disclaimer: This library provides a bridge for Solidity to interact with Solana's system instructions. Although it is production ready,
+// it has not been audited for security, so use it at your own risk.
+
+import 'solana';
+
+library SystemInstruction {
+    address constant systemAddress = address"11111111111111111111111111111111";
+    address constant recentBlockHashes = address"SysvarRecentB1ockHashes11111111111111111111";
+    address constant rentAddress = address"SysvarRent111111111111111111111111111111111";
+    uint64 constant state_size = 80;
+
+    enum Instruction {
+        CreateAccount,
+        Assign,
+        Transfer,
+        CreateAccountWithSeed,
+        AdvanceNounceAccount,
+        WithdrawNonceAccount,
+        InitializeNonceAccount,
+        AuthorizeNonceAccount,
+        Allocate,
+        AllocateWithSeed,
+        AssignWithSeed,
+        TransferWithSeed,
+        UpgradeNonceAccount // This is not available on Solana v1.9.15
+    }
+
+    /// Create a new account on Solana
+    ///
+    /// @param from public key for the account from which to transfer lamports to the new account
+    /// @param to public key for the account to be created
+    /// @param lamports amount of lamports to be transfered to the new account
+    /// @param space the size in bytes that is going to be made available for the account
+    /// @param owner public key for the program that will own the account being created
+    function create_account(address from, address to, uint64 lamports, uint64 space, address owner) internal {
+        AccountMeta[2] metas = [
+            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
+            AccountMeta({pubkey: to, is_signer: true, is_writable: true})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.CreateAccount), lamports, space, owner);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Create a new account on Solana using a public key derived from a seed
+    ///
+    /// @param from public key for the account from which to transfer lamports to the new account
+    /// @param to the public key for the account to be created. The public key must match create_with_seed(base, seed, owner)
+    /// @param base the base address that derived the 'to' address using the seed
+    /// @param seed the string utilized to created the 'to' public key
+    /// @param lamports amount of lamports to be transfered to the new account
+    /// @param space the size in bytes that is going to be made available for the account
+    /// @param owner public key for the program that will own the account being created
+    function create_account_with_seed(address from, address to, address base, string seed, uint64 lamports, uint64 space, address owner) internal {
+        AccountMeta[3] metas = [
+            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
+            AccountMeta({pubkey: to, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
+        ];
+
+        uint32 buffer_size = 92 + seed.length;
+        bytes bincode = new bytes(buffer_size);
+        bincode.writeUint32LE(uint32(Instruction.CreateAccountWithSeed), 0);
+        bincode.writeAddress(base, 4);
+        bincode.writeUint64LE(uint64(seed.length), 36);
+        bincode.writeString(seed, 44);
+        uint32 offset = seed.length + 44;
+        bincode.writeUint64LE(lamports, offset);
+        offset += 8;
+        bincode.writeUint64LE(space, offset);
+        offset += 8;
+        bincode.writeAddress(owner, offset);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Assign account to a program (owner)
+    ///
+    /// @param pubkey the public key for the account whose owner is going to be reassigned
+    /// @param owner the public key for the new account owner
+    function assign(address pubkey, address owner) internal {
+        AccountMeta[1] meta = [
+            AccountMeta({pubkey: pubkey, is_signer: true, is_writable: true})
+        ];
+        bytes bincode = abi.encode(uint32(Instruction.Assign), owner);
+
+        systemAddress.call{accounts: meta}(bincode);
+    }
+
+    /// Assign account to a program (owner) based on a seed
+    ///
+    /// @param addr the public key for the account whose owner is going to be reassigned. The public key must match create_with_seed(base, seed, owner)
+    /// @param base the base address that derived the 'addr' key using the seed
+    /// @param seed the string utilized to created the 'addr' public key
+    /// @param owner the public key for the new program owner
+    function assign_with_seed(address addr, address base, string seed, address owner) internal {
+        AccountMeta[2] metas = [
+            AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
+        ];
+
+
+        uint32 buffer_size = 76 + seed.length;
+        bytes bincode = new bytes(buffer_size);
+        bincode.writeUint32LE(uint32(Instruction.AssignWithSeed), 0);
+        bincode.writeAddress(base, 4);
+        bincode.writeUint64LE(uint64(seed.length), 36);
+        bincode.writeString(seed, 44);
+        bincode.writeAddress(owner, 44 + seed.length);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Transfer lamports between accounts
+    ///
+    /// @param from public key for the funding account
+    /// @param to public key for the recipient account
+    /// @param lamports amount of lamports to transfer
+    function transfer(address from, address to, uint64 lamports) internal {
+        AccountMeta[2] metas = [
+            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
+            AccountMeta({pubkey: to, is_signer: false, is_writable: true})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.Transfer), lamports);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Transfer lamports from a derived address
+    ///
+    /// @param from_pubkey The funding account public key. It should match create_with_seed(from_base, seed, from_owner)
+    /// @param from_base the base address that derived the 'from_pubkey' key using the seed
+    /// @param seed the string utilized to create the 'from_pubkey' public key
+    /// @param from_owner owner to use to derive the funding account address
+    /// @param to_pubkey the public key for the recipient account
+    /// @param lamports amount of lamports to transfer
+    function transfer_with_seed(address from_pubkey, address from_base, string seed, address from_owner, address to_pubkey, uint64 lamports) internal {
+        AccountMeta[3] metas = [
+            AccountMeta({pubkey: from_pubkey, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: from_base, is_signer: true, is_writable: false}),
+            AccountMeta({pubkey: to_pubkey, is_signer: false, is_writable: true})
+        ];
+
+        uint32 buffer_size = seed.length + 52;
+        bytes bincode = new bytes(buffer_size);
+        bincode.writeUint32LE(uint32(Instruction.TransferWithSeed), 0);
+        bincode.writeUint64LE(lamports, 4);
+        bincode.writeUint64LE(seed.length, 12);
+        bincode.writeString(seed, 20);
+        bincode.writeAddress(from_owner, 20 + seed.length);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Allocate space in a (possibly new) account without funding
+    ///
+    /// @param pub_key account for which to allocate space
+    /// @param space number of bytes of memory to allocate
+    function allocate(address pub_key, uint64 space) internal {
+        AccountMeta[1] meta = [
+            AccountMeta({pubkey: pub_key, is_signer: true, is_writable: true})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.Allocate), space);
+
+        systemAddress.call{accounts: meta}(bincode);
+    }
+
+    /// Allocate space for an assign an account at an address derived from a base public key and a seed
+    ///
+    /// @param addr account for which to allocate space. It should match create_with_seed(base, seed, owner)
+    /// @param base the base address that derived the 'addr' key using the seed
+    /// @param seed the string utilized to create the 'addr' public key
+    /// @param space number of bytes of memory to allocate
+    /// @param owner owner to use to derive the 'addr' account address
+    function allocate_with_seed(address addr, address base, string seed, uint64 space, address owner) internal {
+        AccountMeta[2] metas = [
+            AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
+        ];
+
+        bytes bincode = new bytes(seed.length + 84);
+        bincode.writeUint32LE(uint32(Instruction.AllocateWithSeed), 0);
+        bincode.writeAddress(base, 4);
+        bincode.writeUint64LE(seed.length, 36);
+        bincode.writeString(seed, 44);
+        uint32 offset = 44 + seed.length;
+        bincode.writeUint64LE(space, offset);
+        offset += 8;
+        bincode.writeAddress(owner, offset);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Create a new nonce account on Solana using a public key derived from a seed
+    ///
+    /// @param from public key for the account from which to transfer lamports to the new account
+    /// @param nonce the public key for the account to be created. The public key must match create_with_seed(base, seed, systemAddress)
+    /// @param base the base address that derived the 'nonce' key using the seed
+    /// @param seed the string utilized to create the 'addr' public key
+    /// @param authority The entity authorized to execute nonce instructions on the account
+    /// @param lamports amount of lamports to be transfered to the new account
+    function create_nonce_account_with_seed(address from, address nonce, address base, string seed, address authority, uint64 lamports) internal {
+        create_account_with_seed(from, nonce, base, seed, lamports, state_size, systemAddress);
+
+        AccountMeta[3] metas = [
+            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
+            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.InitializeNonceAccount), authority);
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Create a new account on Solana
+    ///
+    /// @param from public key for the account from which to transfer lamports to the new account
+    /// @param nonce the public key for the nonce account to be created
+    /// @param authority The entity authorized to execute nonce instructions on the account
+    /// @param lamports amount of lamports to be transfered to the new account
+    function create_nonce_account(address from, address nonce, address authority, uint64 lamports) internal {
+        create_account(from, nonce, lamports, state_size, systemAddress);
+
+        AccountMeta[3] metas = [
+            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
+            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.InitializeNonceAccount), authority);
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Consumes a stored nonce, replacing it with a successor
+    ///
+    /// @param nonce_pubkey the public key for the nonce account
+    /// @param authorized_pubkey the publick key for the entity authorized to execute instructins on the account
+    function advance_nonce_account(address nonce_pubkey, address authorized_pubkey) internal {
+        AccountMeta[3] metas = [
+            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
+            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.AdvanceNounceAccount));
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Withdraw funds from a nonce account
+    ///
+    /// @param nonce_pubkey the public key for the nonce account
+    /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
+    /// @param to_pubkey the recipient account
+    /// @param lamports the number of lamports to withdraw
+    function withdraw_nonce_account(address nonce_pubkey, address authorized_pubkey, address to_pubkey, uint64 lamports) internal {
+        AccountMeta[5] metas = [
+            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: to_pubkey, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
+            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false}),
+            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.WithdrawNonceAccount), lamports);
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Change the entity authorized to execute nonce instructions on the account
+    ///
+    /// @param nonce_pubkey the public key for the nonce account
+    /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
+    /// @param new_authority
+    function authorize_nonce_account(address nonce_pubkey, address authorized_pubkey, address new_authority) internal {
+        AccountMeta[2] metas = [
+            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.AuthorizeNonceAccount), new_authority);
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// One-time idempotent upgrade of legacy nonce version in order to bump them out of chain domain.
+    ///
+    /// @param nonce the public key for the nonce account
+    // This is not available on Solana v1.9.15
+    function upgrade_nonce_account(address nonce) internal {
+        AccountMeta[1] meta = [
+            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.UpgradeNonceAccount));
+        systemAddress.call{accounts: meta}(bincode);
+    }
+}

+ 1 - 0
tokens/pda-mint-authority/solang/package.json

@@ -6,6 +6,7 @@
     "dependencies": {
         "@coral-xyz/anchor": "^0.28.0",
         "@metaplex-foundation/js": "^0.19.4",
+        "@project-serum/anchor": "^0.26.0",
         "@solana/spl-token": "^0.3.8"
     },
     "devDependencies": {

+ 10 - 9
tokens/pda-mint-authority/solang/solidity/pda-mint-authority.sol

@@ -1,5 +1,5 @@
 
-import "./spl_token.sol";
+import "../libraries/spl_token.sol";
 import "solana";
 
 @program_id("J2eUKE878XKXJZaP7vXwxgWnWnNQMqHSkMPoRFQwa86b")
@@ -8,8 +8,9 @@ contract pda_mint_authority {
 
     @payer(payer)
     @seed("mint_authority") // hard-coded seed
-    @bump(_bump) // bump for the pda address
-    constructor(address payer, bytes1 _bump) {
+    constructor(
+        @bump bytes1 _bump  // bump for the pda address
+    ) {
         // Independently derive the PDA address from the seeds, bump, and programId
         (address pda, bytes1 pdaBump) = try_find_program_address(["mint_authority"], type(pda_mint_authority).program_id);
 
@@ -30,7 +31,7 @@ contract pda_mint_authority {
         string name, // name for the metadata account
         string symbol, // symbol for the metadata account
         string uri // uri for the metadata account
-    ) public view {
+    ) public {
         // Invoke System Program to create a new account for the mint account and,
         // Invoke Token Program to initialize the mint account
         // Set mint authority, freeze authority, and decimals for the mint account
@@ -65,7 +66,7 @@ contract pda_mint_authority {
 		string name, // token name
 		string symbol, // token symbol
 		string uri // token uri
-    ) private view {
+    ) private {
         // // Independently derive the PDA address from the seeds, bump, and programId
         (address pda, bytes1 _bump) = try_find_program_address(["mint_authority"], type(pda_mint_authority).program_id);
 
@@ -119,7 +120,7 @@ contract pda_mint_authority {
         bool usesPresent; // To handle Rust Option<> in Solidity
     }
 
-    function mintTo(address payer, address tokenAccount, address mint, address owner) public view {
+    function mintTo(address payer, address tokenAccount, address mint, address owner) public {
         // Create an associated token account for the owner to receive the minted token
         SplToken.create_associated_token_account(
             payer, // payer account
@@ -142,7 +143,7 @@ contract pda_mint_authority {
     }
 
     // Invoke the token program to mint tokens to a token account, using a PDA as the mint authority
-    function _mintTo(address mint, address account, uint64 amount) private view {
+    function _mintTo(address mint, address account, uint64 amount) private {
         // Independently derive the PDA address from the seeds, bump, and programId
         (address pda, bytes1 _bump) = try_find_program_address(["mint_authority"], type(pda_mint_authority).program_id);
         require(address(this) == pda, 'INVALID_PDA');
@@ -150,7 +151,7 @@ contract pda_mint_authority {
         // Prepare instruction data
         bytes instructionData = new bytes(9);
         instructionData[0] = uint8(7); // MintTo instruction index
-        instructionData.writeUint64LE(1, 1); // Amount to mint
+        instructionData.writeUint64LE(amount, 1); // Amount to mint
 
         // Prepare accounts required by instruction
         AccountMeta[3] metas = [
@@ -163,7 +164,7 @@ contract pda_mint_authority {
         SplToken.tokenProgramId.call{accounts: metas, seeds: [["mint_authority", abi.encode(_bump)]]}(instructionData);
     }
 
-    function _removeMintAuthority(address mintAccount) private view {
+    function _removeMintAuthority(address mintAccount) private {
         // Independently derive the PDA address from the seeds, bump, and programId
         (address pda, bytes1 _bump) = try_find_program_address(["mint_authority"], type(pda_mint_authority).program_id);
         require(address(this) == pda, 'INVALID_PDA');

+ 0 - 300
tokens/pda-mint-authority/solang/solidity/system_instruction.sol

@@ -1,300 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-// Disclaimer: This library provides a bridge for Solidity to interact with Solana's system instructions. Although it is production ready,
-// it has not been audited for security, so use it at your own risk.
-
-import 'solana';
-
-library SystemInstruction {
-    address constant systemAddress = address"11111111111111111111111111111111";
-    address constant recentBlockHashes = address"SysvarRecentB1ockHashes11111111111111111111";
-    address constant rentAddress = address"SysvarRent111111111111111111111111111111111";
-    uint64 constant state_size = 80;
-
-    enum Instruction {
-        CreateAccount,
-        Assign,
-        Transfer,
-        CreateAccountWithSeed,
-        AdvanceNounceAccount,
-        WithdrawNonceAccount,
-        InitializeNonceAccount,
-        AuthorizeNonceAccount,
-        Allocate,
-        AllocateWithSeed,
-        AssignWithSeed,
-        TransferWithSeed,
-        UpgradeNonceAccount // This is not available on Solana v1.9.15
-    }
-
-    /// Create a new account on Solana
-    ///
-    /// @param from public key for the account from which to transfer lamports to the new account
-    /// @param to public key for the account to be created
-    /// @param lamports amount of lamports to be transfered to the new account
-    /// @param space the size in bytes that is going to be made available for the account
-    /// @param owner public key for the program that will own the account being created
-    function create_account(address from, address to, uint64 lamports, uint64 space, address owner) internal view {
-        AccountMeta[2] metas = [
-            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
-            AccountMeta({pubkey: to, is_signer: true, is_writable: true})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.CreateAccount), lamports, space, owner);
-
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Create a new account on Solana using a public key derived from a seed
-    ///
-    /// @param from public key for the account from which to transfer lamports to the new account
-    /// @param to the public key for the account to be created. The public key must match create_with_seed(base, seed, owner)
-    /// @param base the base address that derived the 'to' address using the seed
-    /// @param seed the string utilized to created the 'to' public key
-    /// @param lamports amount of lamports to be transfered to the new account
-    /// @param space the size in bytes that is going to be made available for the account
-    /// @param owner public key for the program that will own the account being created
-    function create_account_with_seed(address from, address to, address base, string seed, uint64 lamports, uint64 space, address owner) internal view {
-        AccountMeta[3] metas = [
-            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
-            AccountMeta({pubkey: to, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
-        ];
-
-        uint32 buffer_size = 92 + seed.length;
-        bytes bincode = new bytes(buffer_size);
-        bincode.writeUint32LE(uint32(Instruction.CreateAccountWithSeed), 0);
-        bincode.writeAddress(base, 4);
-        bincode.writeUint64LE(uint64(seed.length), 36);
-        bincode.writeString(seed, 44);
-        uint32 offset = seed.length + 44;
-        bincode.writeUint64LE(lamports, offset);
-        offset += 8;
-        bincode.writeUint64LE(space, offset);
-        offset += 8;
-        bincode.writeAddress(owner, offset);
-
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Assign account to a program (owner)
-    ///
-    /// @param pubkey the public key for the account whose owner is going to be reassigned
-    /// @param owner the public key for the new account owner
-    function assign(address pubkey, address owner) internal view {
-        AccountMeta[1] meta = [
-            AccountMeta({pubkey: pubkey, is_signer: true, is_writable: true})
-        ];
-        bytes bincode = abi.encode(uint32(Instruction.Assign), owner);
-
-        systemAddress.call{accounts: meta}(bincode);
-    }
-
-    /// Assign account to a program (owner) based on a seed
-    ///
-    /// @param addr the public key for the account whose owner is going to be reassigned. The public key must match create_with_seed(base, seed, owner)
-    /// @param base the base address that derived the 'addr' key using the seed
-    /// @param seed the string utilized to created the 'addr' public key
-    /// @param owner the public key for the new program owner
-    function assign_with_seed(address addr, address base, string seed, address owner) internal view {
-        AccountMeta[2] metas = [
-            AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
-        ];
-
-
-        uint32 buffer_size = 76 + seed.length;
-        bytes bincode = new bytes(buffer_size);
-        bincode.writeUint32LE(uint32(Instruction.AssignWithSeed), 0);
-        bincode.writeAddress(base, 4);
-        bincode.writeUint64LE(uint64(seed.length), 36);
-        bincode.writeString(seed, 44);
-        bincode.writeAddress(owner, 44 + seed.length);
-
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Transfer lamports between accounts
-    ///
-    /// @param from public key for the funding account
-    /// @param to public key for the recipient account
-    /// @param lamports amount of lamports to transfer
-    function transfer(address from, address to, uint64 lamports) internal view {
-        AccountMeta[2] metas = [
-            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
-            AccountMeta({pubkey: to, is_signer: false, is_writable: true})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.Transfer), lamports);
-
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Transfer lamports from a derived address
-    ///
-    /// @param from_pubkey The funding account public key. It should match create_with_seed(from_base, seed, from_owner)
-    /// @param from_base the base address that derived the 'from_pubkey' key using the seed
-    /// @param seed the string utilized to create the 'from_pubkey' public key
-    /// @param from_owner owner to use to derive the funding account address
-    /// @param to_pubkey the public key for the recipient account
-    /// @param lamports amount of lamports to transfer
-    function transfer_with_seed(address from_pubkey, address from_base, string seed, address from_owner, address to_pubkey, uint64 lamports) internal view {
-        AccountMeta[3] metas = [
-            AccountMeta({pubkey: from_pubkey, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: from_base, is_signer: true, is_writable: false}),
-            AccountMeta({pubkey: to_pubkey, is_signer: false, is_writable: true})
-        ];
-
-        uint32 buffer_size = seed.length + 52;
-        bytes bincode = new bytes(buffer_size);
-        bincode.writeUint32LE(uint32(Instruction.TransferWithSeed), 0);
-        bincode.writeUint64LE(lamports, 4);
-        bincode.writeUint64LE(seed.length, 12);
-        bincode.writeString(seed, 20);
-        bincode.writeAddress(from_owner, 20 + seed.length);
-
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Allocate space in a (possibly new) account without funding
-    ///
-    /// @param pub_key account for which to allocate space
-    /// @param space number of bytes of memory to allocate
-    function allocate(address pub_key, uint64 space) internal view {
-        AccountMeta[1] meta = [
-            AccountMeta({pubkey: pub_key, is_signer: true, is_writable: true})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.Allocate), space);
-
-        systemAddress.call{accounts: meta}(bincode);
-    }
-
-    /// Allocate space for an assign an account at an address derived from a base public key and a seed
-    ///
-    /// @param addr account for which to allocate space. It should match create_with_seed(base, seed, owner)
-    /// @param base the base address that derived the 'addr' key using the seed
-    /// @param seed the string utilized to create the 'addr' public key
-    /// @param space number of bytes of memory to allocate
-    /// @param owner owner to use to derive the 'addr' account address
-    function allocate_with_seed(address addr, address base, string seed, uint64 space, address owner) internal view {
-        AccountMeta[2] metas = [
-            AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
-        ];
-
-        bytes bincode = new bytes(seed.length + 84);
-        bincode.writeUint32LE(uint32(Instruction.AllocateWithSeed), 0);
-        bincode.writeAddress(base, 4);
-        bincode.writeUint64LE(seed.length, 36);
-        bincode.writeString(seed, 44);
-        uint32 offset = 44 + seed.length;
-        bincode.writeUint64LE(space, offset);
-        offset += 8;
-        bincode.writeAddress(owner, offset);
-
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Create a new nonce account on Solana using a public key derived from a seed
-    ///
-    /// @param from public key for the account from which to transfer lamports to the new account
-    /// @param nonce the public key for the account to be created. The public key must match create_with_seed(base, seed, systemAddress)
-    /// @param base the base address that derived the 'nonce' key using the seed
-    /// @param seed the string utilized to create the 'addr' public key
-    /// @param authority The entity authorized to execute nonce instructions on the account
-    /// @param lamports amount of lamports to be transfered to the new account
-    function create_nonce_account_with_seed(address from, address nonce, address base, string seed, address authority, uint64 lamports) internal view {
-        create_account_with_seed(from, nonce, base, seed, lamports, state_size, systemAddress);
-
-        AccountMeta[3] metas = [
-            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
-            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.InitializeNonceAccount), authority);
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Create a new account on Solana
-    ///
-    /// @param from public key for the account from which to transfer lamports to the new account
-    /// @param nonce the public key for the nonce account to be created
-    /// @param authority The entity authorized to execute nonce instructions on the account
-    /// @param lamports amount of lamports to be transfered to the new account
-    function create_nonce_account(address from, address nonce, address authority, uint64 lamports) internal view {
-        create_account(from, nonce, lamports, state_size, systemAddress);
-
-        AccountMeta[3] metas = [
-            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
-            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.InitializeNonceAccount), authority);
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Consumes a stored nonce, replacing it with a successor
-    ///
-    /// @param nonce_pubkey the public key for the nonce account
-    /// @param authorized_pubkey the publick key for the entity authorized to execute instructins on the account
-    function advance_nonce_account(address nonce_pubkey, address authorized_pubkey) internal view {
-        AccountMeta[3] metas = [
-            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
-            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.AdvanceNounceAccount));
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Withdraw funds from a nonce account
-    ///
-    /// @param nonce_pubkey the public key for the nonce account
-    /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
-    /// @param to_pubkey the recipient account
-    /// @param lamports the number of lamports to withdraw
-    function withdraw_nonce_account(address nonce_pubkey, address authorized_pubkey, address to_pubkey, uint64 lamports) internal view {
-        AccountMeta[5] metas = [
-            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: to_pubkey, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
-            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false}),
-            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.WithdrawNonceAccount), lamports);
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Change the entity authorized to execute nonce instructions on the account
-    ///
-    /// @param nonce_pubkey the public key for the nonce account
-    /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
-    /// @param new_authority
-    function authorize_nonce_account(address nonce_pubkey, address authorized_pubkey, address new_authority) internal view {
-        AccountMeta[2] metas = [
-            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.AuthorizeNonceAccount), new_authority);
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// One-time idempotent upgrade of legacy nonce version in order to bump them out of chain domain.
-    ///
-    /// @param nonce the public key for the nonce account
-    // This is not available on Solana v1.9.15
-    function upgrade_nonce_account(address nonce) internal view {
-        AccountMeta[1] meta = [
-            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.UpgradeNonceAccount));
-        systemAddress.call{accounts: meta}(bincode);
-    }
-}

+ 31 - 30
tokens/pda-mint-authority/solang/tests/pda-mint-authority.ts

@@ -1,51 +1,52 @@
-import * as anchor from "@coral-xyz/anchor"
-import { Program } from "@coral-xyz/anchor"
-import { PdaMintAuthority } from "../target/types/pda_mint_authority"
-import { PublicKey, SystemProgram, SYSVAR_RENT_PUBKEY } from "@solana/web3.js"
-import { Metaplex } from "@metaplex-foundation/js"
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { PdaMintAuthority } from "../target/types/pda_mint_authority";
+import { PublicKey, SystemProgram, SYSVAR_RENT_PUBKEY } from "@solana/web3.js";
+import { Metaplex } from "@metaplex-foundation/js";
 import {
   ASSOCIATED_TOKEN_PROGRAM_ID,
   getAssociatedTokenAddressSync,
   TOKEN_PROGRAM_ID,
-} from "@solana/spl-token"
+} from "@solana/spl-token";
 
 describe("pda-mint-authority", () => {
   // Configure the client to use the local cluster.
-  const provider = anchor.AnchorProvider.env()
-  anchor.setProvider(provider)
+  const provider = anchor.AnchorProvider.env();
+  anchor.setProvider(provider);
 
-  const mintKeypair = anchor.web3.Keypair.generate()
-  const wallet = provider.wallet
-  const connection = provider.connection
+  const mintKeypair = anchor.web3.Keypair.generate();
+  const wallet = provider.wallet;
+  const connection = provider.connection;
 
-  const program = anchor.workspace.PdaMintAuthority as Program<PdaMintAuthority>
+  const program = anchor.workspace
+    .PdaMintAuthority as Program<PdaMintAuthority>;
 
   // Derive the PDA that will be used to initialize the dataAccount.
   const [dataAccountPDA, bump] = PublicKey.findProgramAddressSync(
     [Buffer.from("mint_authority")],
     program.programId
-  )
+  );
 
-  const nftTitle = "Homer NFT"
-  const nftSymbol = "HOMR"
+  const nftTitle = "Homer NFT";
+  const nftSymbol = "HOMR";
   const nftUri =
-    "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/nft.json"
+    "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/nft.json";
 
   it("Is initialized!", async () => {
     // Add your test here.
     const tx = await program.methods
-      .new(wallet.publicKey, [bump])
+      .new([bump])
       .accounts({ dataAccount: dataAccountPDA })
-      .rpc()
-    console.log("Your transaction signature", tx)
-  })
+      .rpc();
+    console.log("Your transaction signature", tx);
+  });
 
   it("Create an NFT!", async () => {
-    const metaplex = Metaplex.make(connection)
+    const metaplex = Metaplex.make(connection);
     const metadataAddress = await metaplex
       .nfts()
       .pdas()
-      .metadata({ mint: mintKeypair.publicKey })
+      .metadata({ mint: mintKeypair.publicKey });
 
     // Add your test here.
     const tx = await program.methods
@@ -78,16 +79,16 @@ describe("pda-mint-authority", () => {
         { pubkey: SYSVAR_RENT_PUBKEY, isWritable: false, isSigner: false },
       ])
       .signers([mintKeypair])
-      .rpc({ skipPreflight: true })
-    console.log("Your transaction signature", tx)
-  })
+      .rpc({ skipPreflight: true });
+    console.log("Your transaction signature", tx);
+  });
 
   it("Mint the NFT to your wallet!", async () => {
     // Derive wallet's associated token account address for mint
     const tokenAccount = getAssociatedTokenAddressSync(
       mintKeypair.publicKey,
       wallet.publicKey
-    )
+    );
 
     const tx = await program.methods
       .mintTo(
@@ -118,7 +119,7 @@ describe("pda-mint-authority", () => {
           isSigner: false,
         },
       ])
-      .rpc({ skipPreflight: true })
-    console.log("Your transaction signature", tx)
-  })
-})
+      .rpc({ skipPreflight: true });
+    console.log("Your transaction signature", tx);
+  });
+});

+ 9 - 9
tokens/pda-mint-authority/solang/tsconfig.json

@@ -1,11 +1,11 @@
 {
-            "compilerOptions": {
-              "types": ["mocha", "chai"],
-              "typeRoots": ["./node_modules/@types"],
-              "lib": ["es2015"],
-              "module": "commonjs",
-              "target": "es6",
-              "esModuleInterop": true
-            }
-          }
+  "compilerOptions": {
+    "types": ["mocha", "chai"],
+    "typeRoots": ["./node_modules/@types"],
+    "lib": ["es2015"],
+    "module": "commonjs",
+    "target": "es6",
+    "esModuleInterop": true
+  }
+}
           

+ 1 - 1
tokens/create-token/solang/solidity/mpl_metadata.sol → tokens/spl-token-minter/solang/libraries/mpl_metadata.sol

@@ -77,7 +77,7 @@ library MplMetadata {
 		string name,
 		string symbol,
 		string uri
-	) public view {
+	) public {
         // // Example of how to add a Creator[] array to the DataV2 struct
 		// Creator[] memory creators = new Creator[](1);
         // creators[0] = Creator({

+ 10 - 10
tokens/create-token/solang/solidity/spl_token.sol → tokens/spl-token-minter/solang/libraries/spl_token.sol

@@ -45,7 +45,7 @@ library SplToken {
 	/// @param tokenAccount the public key of the token account to initialize
 	/// @param mint the public key of the mint account for this new token account
 	/// @param owner the public key of the owner of this new token account
-	function initialize_account(address tokenAccount, address mint, address owner) internal view{
+	function initialize_account(address tokenAccount, address mint, address owner) internal{
 		bytes instr = new bytes(1);
 
 		instr[0] = uint8(TokenInstruction.InitializeAccount);
@@ -65,7 +65,7 @@ library SplToken {
 	/// @param tokenAccount the public key of the token account to initialize
 	/// @param mint the public key of the mint account for this new token account
 	/// @param owner the public key of the owner of this new token account
-    function create_associated_token_account(address payer, address tokenAccount, address mint, address owner) internal view {
+    function create_associated_token_account(address payer, address tokenAccount, address mint, address owner) internal {
         AccountMeta[6] metas = [
 			AccountMeta({pubkey: payer, is_writable: true, is_signer: true}),
 			AccountMeta({pubkey: tokenAccount, is_writable: true, is_signer: false}),
@@ -94,7 +94,7 @@ library SplToken {
 	/// @param mintAuthority the public key of the mint authority
 	/// @param freezeAuthority the public key of the freeze authority
 	/// @param decimals the decimals of the mint
-	function initialize_mint(address mint, address mintAuthority, address freezeAuthority, uint8 decimals) internal view {
+	function initialize_mint(address mint, address mintAuthority, address freezeAuthority, uint8 decimals) internal {
     	InitializeMintInstruction instr = InitializeMintInstruction({
             instruction: 20,
             decimals: decimals,
@@ -117,7 +117,7 @@ library SplToken {
 	/// @param mintAuthority the public key of the mint authority
 	/// @param freezeAuthority the public key of the freeze authority
 	/// @param decimals the decimals of the mint
-	function create_mint(address payer, address mint, address mintAuthority, address freezeAuthority, uint8 decimals) internal view {
+	function create_mint(address payer, address mint, address mintAuthority, address freezeAuthority, uint8 decimals) internal {
 		// Invoke System Program to create a new account for the mint account
         // Program owner is set to the Token program
         SystemInstruction.create_account(
@@ -149,7 +149,7 @@ library SplToken {
 	/// @param account the token account where the minted tokens should go
 	/// @param authority the public key of the mint authority
 	/// @param amount the amount of tokens to mint
-	function mint_to(address mint, address account, address authority, uint64 amount) internal view {
+	function mint_to(address mint, address account, address authority, uint64 amount) internal {
 		bytes instr = new bytes(9);
 
 		instr[0] = uint8(TokenInstruction.MintTo);
@@ -171,7 +171,7 @@ library SplToken {
 	/// @param to the account to transfer tokens to
 	/// @param owner the publickey of the from account owner keypair
 	/// @param amount the amount to transfer
-	function transfer(address from, address to, address owner, uint64 amount) internal view {
+	function transfer(address from, address to, address owner, uint64 amount) internal {
 		bytes instr = new bytes(9);
 
 		instr[0] = uint8(TokenInstruction.Transfer);
@@ -192,7 +192,7 @@ library SplToken {
 	/// @param mint the mint for this token
 	/// @param owner the publickey of the account owner keypair
 	/// @param amount the amount to transfer
-	function burn(address account, address mint, address owner, uint64 amount) internal view {
+	function burn(address account, address mint, address owner, uint64 amount) internal {
 		bytes instr = new bytes(9);
 
 		instr[0] = uint8(TokenInstruction.Burn);
@@ -213,7 +213,7 @@ library SplToken {
 	/// @param delegate the delegate publickey
 	/// @param owner the publickey of the account owner keypair
 	/// @param amount the amount to approve
-	function approve(address account, address delegate, address owner, uint64 amount) internal view {
+	function approve(address account, address delegate, address owner, uint64 amount) internal {
 		bytes instr = new bytes(9);
 
 		instr[0] = uint8(TokenInstruction.Approve);
@@ -233,7 +233,7 @@ library SplToken {
 	///
 	/// @param account the account for which a delegate should be approved
 	/// @param owner the publickey of the account owner keypair
-	function revoke(address account, address owner) internal view {
+	function revoke(address account, address owner) internal {
 		bytes instr = new bytes(1);
 
 		instr[0] = uint8(TokenInstruction.Revoke);
@@ -371,7 +371,7 @@ library SplToken {
 	///
 	/// @param mintAccount the public key for the mint account
 	/// @param mintAuthority the public for the mint authority
-	function remove_mint_authority(address mintAccount, address mintAuthority) public view {
+	function remove_mint_authority(address mintAccount, address mintAuthority) public {
 		AccountMeta[2] metas = [
 			AccountMeta({pubkey: mintAccount, is_signer: false, is_writable: true}),
 			AccountMeta({pubkey: mintAuthority, is_signer: true, is_writable: false})

+ 300 - 0
tokens/spl-token-minter/solang/libraries/system_instruction.sol

@@ -0,0 +1,300 @@
+// SPDX-License-Identifier: Apache-2.0
+
+// Disclaimer: This library provides a bridge for Solidity to interact with Solana's system instructions. Although it is production ready,
+// it has not been audited for security, so use it at your own risk.
+
+import 'solana';
+
+library SystemInstruction {
+    address constant systemAddress = address"11111111111111111111111111111111";
+    address constant recentBlockHashes = address"SysvarRecentB1ockHashes11111111111111111111";
+    address constant rentAddress = address"SysvarRent111111111111111111111111111111111";
+    uint64 constant state_size = 80;
+
+    enum Instruction {
+        CreateAccount,
+        Assign,
+        Transfer,
+        CreateAccountWithSeed,
+        AdvanceNounceAccount,
+        WithdrawNonceAccount,
+        InitializeNonceAccount,
+        AuthorizeNonceAccount,
+        Allocate,
+        AllocateWithSeed,
+        AssignWithSeed,
+        TransferWithSeed,
+        UpgradeNonceAccount // This is not available on Solana v1.9.15
+    }
+
+    /// Create a new account on Solana
+    ///
+    /// @param from public key for the account from which to transfer lamports to the new account
+    /// @param to public key for the account to be created
+    /// @param lamports amount of lamports to be transfered to the new account
+    /// @param space the size in bytes that is going to be made available for the account
+    /// @param owner public key for the program that will own the account being created
+    function create_account(address from, address to, uint64 lamports, uint64 space, address owner) internal {
+        AccountMeta[2] metas = [
+            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
+            AccountMeta({pubkey: to, is_signer: true, is_writable: true})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.CreateAccount), lamports, space, owner);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Create a new account on Solana using a public key derived from a seed
+    ///
+    /// @param from public key for the account from which to transfer lamports to the new account
+    /// @param to the public key for the account to be created. The public key must match create_with_seed(base, seed, owner)
+    /// @param base the base address that derived the 'to' address using the seed
+    /// @param seed the string utilized to created the 'to' public key
+    /// @param lamports amount of lamports to be transfered to the new account
+    /// @param space the size in bytes that is going to be made available for the account
+    /// @param owner public key for the program that will own the account being created
+    function create_account_with_seed(address from, address to, address base, string seed, uint64 lamports, uint64 space, address owner) internal {
+        AccountMeta[3] metas = [
+            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
+            AccountMeta({pubkey: to, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
+        ];
+
+        uint32 buffer_size = 92 + seed.length;
+        bytes bincode = new bytes(buffer_size);
+        bincode.writeUint32LE(uint32(Instruction.CreateAccountWithSeed), 0);
+        bincode.writeAddress(base, 4);
+        bincode.writeUint64LE(uint64(seed.length), 36);
+        bincode.writeString(seed, 44);
+        uint32 offset = seed.length + 44;
+        bincode.writeUint64LE(lamports, offset);
+        offset += 8;
+        bincode.writeUint64LE(space, offset);
+        offset += 8;
+        bincode.writeAddress(owner, offset);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Assign account to a program (owner)
+    ///
+    /// @param pubkey the public key for the account whose owner is going to be reassigned
+    /// @param owner the public key for the new account owner
+    function assign(address pubkey, address owner) internal {
+        AccountMeta[1] meta = [
+            AccountMeta({pubkey: pubkey, is_signer: true, is_writable: true})
+        ];
+        bytes bincode = abi.encode(uint32(Instruction.Assign), owner);
+
+        systemAddress.call{accounts: meta}(bincode);
+    }
+
+    /// Assign account to a program (owner) based on a seed
+    ///
+    /// @param addr the public key for the account whose owner is going to be reassigned. The public key must match create_with_seed(base, seed, owner)
+    /// @param base the base address that derived the 'addr' key using the seed
+    /// @param seed the string utilized to created the 'addr' public key
+    /// @param owner the public key for the new program owner
+    function assign_with_seed(address addr, address base, string seed, address owner) internal {
+        AccountMeta[2] metas = [
+            AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
+        ];
+
+
+        uint32 buffer_size = 76 + seed.length;
+        bytes bincode = new bytes(buffer_size);
+        bincode.writeUint32LE(uint32(Instruction.AssignWithSeed), 0);
+        bincode.writeAddress(base, 4);
+        bincode.writeUint64LE(uint64(seed.length), 36);
+        bincode.writeString(seed, 44);
+        bincode.writeAddress(owner, 44 + seed.length);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Transfer lamports between accounts
+    ///
+    /// @param from public key for the funding account
+    /// @param to public key for the recipient account
+    /// @param lamports amount of lamports to transfer
+    function transfer(address from, address to, uint64 lamports) internal {
+        AccountMeta[2] metas = [
+            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
+            AccountMeta({pubkey: to, is_signer: false, is_writable: true})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.Transfer), lamports);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Transfer lamports from a derived address
+    ///
+    /// @param from_pubkey The funding account public key. It should match create_with_seed(from_base, seed, from_owner)
+    /// @param from_base the base address that derived the 'from_pubkey' key using the seed
+    /// @param seed the string utilized to create the 'from_pubkey' public key
+    /// @param from_owner owner to use to derive the funding account address
+    /// @param to_pubkey the public key for the recipient account
+    /// @param lamports amount of lamports to transfer
+    function transfer_with_seed(address from_pubkey, address from_base, string seed, address from_owner, address to_pubkey, uint64 lamports) internal {
+        AccountMeta[3] metas = [
+            AccountMeta({pubkey: from_pubkey, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: from_base, is_signer: true, is_writable: false}),
+            AccountMeta({pubkey: to_pubkey, is_signer: false, is_writable: true})
+        ];
+
+        uint32 buffer_size = seed.length + 52;
+        bytes bincode = new bytes(buffer_size);
+        bincode.writeUint32LE(uint32(Instruction.TransferWithSeed), 0);
+        bincode.writeUint64LE(lamports, 4);
+        bincode.writeUint64LE(seed.length, 12);
+        bincode.writeString(seed, 20);
+        bincode.writeAddress(from_owner, 20 + seed.length);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Allocate space in a (possibly new) account without funding
+    ///
+    /// @param pub_key account for which to allocate space
+    /// @param space number of bytes of memory to allocate
+    function allocate(address pub_key, uint64 space) internal {
+        AccountMeta[1] meta = [
+            AccountMeta({pubkey: pub_key, is_signer: true, is_writable: true})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.Allocate), space);
+
+        systemAddress.call{accounts: meta}(bincode);
+    }
+
+    /// Allocate space for an assign an account at an address derived from a base public key and a seed
+    ///
+    /// @param addr account for which to allocate space. It should match create_with_seed(base, seed, owner)
+    /// @param base the base address that derived the 'addr' key using the seed
+    /// @param seed the string utilized to create the 'addr' public key
+    /// @param space number of bytes of memory to allocate
+    /// @param owner owner to use to derive the 'addr' account address
+    function allocate_with_seed(address addr, address base, string seed, uint64 space, address owner) internal {
+        AccountMeta[2] metas = [
+            AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
+        ];
+
+        bytes bincode = new bytes(seed.length + 84);
+        bincode.writeUint32LE(uint32(Instruction.AllocateWithSeed), 0);
+        bincode.writeAddress(base, 4);
+        bincode.writeUint64LE(seed.length, 36);
+        bincode.writeString(seed, 44);
+        uint32 offset = 44 + seed.length;
+        bincode.writeUint64LE(space, offset);
+        offset += 8;
+        bincode.writeAddress(owner, offset);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Create a new nonce account on Solana using a public key derived from a seed
+    ///
+    /// @param from public key for the account from which to transfer lamports to the new account
+    /// @param nonce the public key for the account to be created. The public key must match create_with_seed(base, seed, systemAddress)
+    /// @param base the base address that derived the 'nonce' key using the seed
+    /// @param seed the string utilized to create the 'addr' public key
+    /// @param authority The entity authorized to execute nonce instructions on the account
+    /// @param lamports amount of lamports to be transfered to the new account
+    function create_nonce_account_with_seed(address from, address nonce, address base, string seed, address authority, uint64 lamports) internal {
+        create_account_with_seed(from, nonce, base, seed, lamports, state_size, systemAddress);
+
+        AccountMeta[3] metas = [
+            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
+            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.InitializeNonceAccount), authority);
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Create a new account on Solana
+    ///
+    /// @param from public key for the account from which to transfer lamports to the new account
+    /// @param nonce the public key for the nonce account to be created
+    /// @param authority The entity authorized to execute nonce instructions on the account
+    /// @param lamports amount of lamports to be transfered to the new account
+    function create_nonce_account(address from, address nonce, address authority, uint64 lamports) internal {
+        create_account(from, nonce, lamports, state_size, systemAddress);
+
+        AccountMeta[3] metas = [
+            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
+            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.InitializeNonceAccount), authority);
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Consumes a stored nonce, replacing it with a successor
+    ///
+    /// @param nonce_pubkey the public key for the nonce account
+    /// @param authorized_pubkey the publick key for the entity authorized to execute instructins on the account
+    function advance_nonce_account(address nonce_pubkey, address authorized_pubkey) internal {
+        AccountMeta[3] metas = [
+            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
+            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.AdvanceNounceAccount));
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Withdraw funds from a nonce account
+    ///
+    /// @param nonce_pubkey the public key for the nonce account
+    /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
+    /// @param to_pubkey the recipient account
+    /// @param lamports the number of lamports to withdraw
+    function withdraw_nonce_account(address nonce_pubkey, address authorized_pubkey, address to_pubkey, uint64 lamports) internal {
+        AccountMeta[5] metas = [
+            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: to_pubkey, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
+            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false}),
+            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.WithdrawNonceAccount), lamports);
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Change the entity authorized to execute nonce instructions on the account
+    ///
+    /// @param nonce_pubkey the public key for the nonce account
+    /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
+    /// @param new_authority
+    function authorize_nonce_account(address nonce_pubkey, address authorized_pubkey, address new_authority) internal {
+        AccountMeta[2] metas = [
+            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.AuthorizeNonceAccount), new_authority);
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// One-time idempotent upgrade of legacy nonce version in order to bump them out of chain domain.
+    ///
+    /// @param nonce the public key for the nonce account
+    // This is not available on Solana v1.9.15
+    function upgrade_nonce_account(address nonce) internal {
+        AccountMeta[1] meta = [
+            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.UpgradeNonceAccount));
+        systemAddress.call{accounts: meta}(bincode);
+    }
+}

+ 1 - 0
tokens/spl-token-minter/solang/package.json

@@ -6,6 +6,7 @@
     "dependencies": {
         "@coral-xyz/anchor": "^0.28.0",
         "@metaplex-foundation/js": "^0.19.4",
+        "@project-serum/anchor": "^0.26.0",
         "@solana/spl-token": "^0.3.8"
     },
     "devDependencies": {

+ 6 - 6
tokens/spl-token-minter/solang/solidity/spl-token-minter.sol

@@ -1,11 +1,11 @@
 
-import "./spl_token.sol";
-import "./mpl_metadata.sol";
+import "../libraries/spl_token.sol";
+import "../libraries/mpl_metadata.sol";
 
 @program_id("F1ipperKF9EfD821ZbbYjS319LXYiBmjhzkkf5a26rC")
 contract spl_token_minter {
     @payer(payer)
-    constructor(address payer) {}
+    constructor() {}
 
     function createTokenMint(
         address payer, // payer account
@@ -17,7 +17,7 @@ contract spl_token_minter {
         string name, // name for the metadata account
         string symbol, // symbol for the metadata account
         string uri // uri for the metadata account
-    ) public view {
+    ) public {
         // Invoke System Program to create a new account for the mint account and,
         // Invoke Token Program to initialize the mint account
         // Set mint authority, freeze authority, and decimals for the mint account
@@ -42,12 +42,12 @@ contract spl_token_minter {
         );
     }
 
-    function mintTo(address payer, address tokenAccount, address mint, address owner, uint64 amount) public view {
+    function mintTo(address mintAuthority, address tokenAccount, address mint, uint64 amount) public {
         // Mint tokens to the token account
         SplToken.mint_to(
             mint, // mint account
             tokenAccount, // token account
-            payer, // mint authority
+            mintAuthority, // mint authority
             amount // amount
         );
     }

+ 0 - 300
tokens/spl-token-minter/solang/solidity/system_instruction.sol

@@ -1,300 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-// Disclaimer: This library provides a bridge for Solidity to interact with Solana's system instructions. Although it is production ready,
-// it has not been audited for security, so use it at your own risk.
-
-import 'solana';
-
-library SystemInstruction {
-    address constant systemAddress = address"11111111111111111111111111111111";
-    address constant recentBlockHashes = address"SysvarRecentB1ockHashes11111111111111111111";
-    address constant rentAddress = address"SysvarRent111111111111111111111111111111111";
-    uint64 constant state_size = 80;
-
-    enum Instruction {
-        CreateAccount,
-        Assign,
-        Transfer,
-        CreateAccountWithSeed,
-        AdvanceNounceAccount,
-        WithdrawNonceAccount,
-        InitializeNonceAccount,
-        AuthorizeNonceAccount,
-        Allocate,
-        AllocateWithSeed,
-        AssignWithSeed,
-        TransferWithSeed,
-        UpgradeNonceAccount // This is not available on Solana v1.9.15
-    }
-
-    /// Create a new account on Solana
-    ///
-    /// @param from public key for the account from which to transfer lamports to the new account
-    /// @param to public key for the account to be created
-    /// @param lamports amount of lamports to be transfered to the new account
-    /// @param space the size in bytes that is going to be made available for the account
-    /// @param owner public key for the program that will own the account being created
-    function create_account(address from, address to, uint64 lamports, uint64 space, address owner) internal view {
-        AccountMeta[2] metas = [
-            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
-            AccountMeta({pubkey: to, is_signer: true, is_writable: true})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.CreateAccount), lamports, space, owner);
-
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Create a new account on Solana using a public key derived from a seed
-    ///
-    /// @param from public key for the account from which to transfer lamports to the new account
-    /// @param to the public key for the account to be created. The public key must match create_with_seed(base, seed, owner)
-    /// @param base the base address that derived the 'to' address using the seed
-    /// @param seed the string utilized to created the 'to' public key
-    /// @param lamports amount of lamports to be transfered to the new account
-    /// @param space the size in bytes that is going to be made available for the account
-    /// @param owner public key for the program that will own the account being created
-    function create_account_with_seed(address from, address to, address base, string seed, uint64 lamports, uint64 space, address owner) internal view {
-        AccountMeta[3] metas = [
-            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
-            AccountMeta({pubkey: to, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
-        ];
-
-        uint32 buffer_size = 92 + seed.length;
-        bytes bincode = new bytes(buffer_size);
-        bincode.writeUint32LE(uint32(Instruction.CreateAccountWithSeed), 0);
-        bincode.writeAddress(base, 4);
-        bincode.writeUint64LE(uint64(seed.length), 36);
-        bincode.writeString(seed, 44);
-        uint32 offset = seed.length + 44;
-        bincode.writeUint64LE(lamports, offset);
-        offset += 8;
-        bincode.writeUint64LE(space, offset);
-        offset += 8;
-        bincode.writeAddress(owner, offset);
-
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Assign account to a program (owner)
-    ///
-    /// @param pubkey the public key for the account whose owner is going to be reassigned
-    /// @param owner the public key for the new account owner
-    function assign(address pubkey, address owner) internal view {
-        AccountMeta[1] meta = [
-            AccountMeta({pubkey: pubkey, is_signer: true, is_writable: true})
-        ];
-        bytes bincode = abi.encode(uint32(Instruction.Assign), owner);
-
-        systemAddress.call{accounts: meta}(bincode);
-    }
-
-    /// Assign account to a program (owner) based on a seed
-    ///
-    /// @param addr the public key for the account whose owner is going to be reassigned. The public key must match create_with_seed(base, seed, owner)
-    /// @param base the base address that derived the 'addr' key using the seed
-    /// @param seed the string utilized to created the 'addr' public key
-    /// @param owner the public key for the new program owner
-    function assign_with_seed(address addr, address base, string seed, address owner) internal view {
-        AccountMeta[2] metas = [
-            AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
-        ];
-
-
-        uint32 buffer_size = 76 + seed.length;
-        bytes bincode = new bytes(buffer_size);
-        bincode.writeUint32LE(uint32(Instruction.AssignWithSeed), 0);
-        bincode.writeAddress(base, 4);
-        bincode.writeUint64LE(uint64(seed.length), 36);
-        bincode.writeString(seed, 44);
-        bincode.writeAddress(owner, 44 + seed.length);
-
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Transfer lamports between accounts
-    ///
-    /// @param from public key for the funding account
-    /// @param to public key for the recipient account
-    /// @param lamports amount of lamports to transfer
-    function transfer(address from, address to, uint64 lamports) internal view {
-        AccountMeta[2] metas = [
-            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
-            AccountMeta({pubkey: to, is_signer: false, is_writable: true})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.Transfer), lamports);
-
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Transfer lamports from a derived address
-    ///
-    /// @param from_pubkey The funding account public key. It should match create_with_seed(from_base, seed, from_owner)
-    /// @param from_base the base address that derived the 'from_pubkey' key using the seed
-    /// @param seed the string utilized to create the 'from_pubkey' public key
-    /// @param from_owner owner to use to derive the funding account address
-    /// @param to_pubkey the public key for the recipient account
-    /// @param lamports amount of lamports to transfer
-    function transfer_with_seed(address from_pubkey, address from_base, string seed, address from_owner, address to_pubkey, uint64 lamports) internal view {
-        AccountMeta[3] metas = [
-            AccountMeta({pubkey: from_pubkey, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: from_base, is_signer: true, is_writable: false}),
-            AccountMeta({pubkey: to_pubkey, is_signer: false, is_writable: true})
-        ];
-
-        uint32 buffer_size = seed.length + 52;
-        bytes bincode = new bytes(buffer_size);
-        bincode.writeUint32LE(uint32(Instruction.TransferWithSeed), 0);
-        bincode.writeUint64LE(lamports, 4);
-        bincode.writeUint64LE(seed.length, 12);
-        bincode.writeString(seed, 20);
-        bincode.writeAddress(from_owner, 20 + seed.length);
-
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Allocate space in a (possibly new) account without funding
-    ///
-    /// @param pub_key account for which to allocate space
-    /// @param space number of bytes of memory to allocate
-    function allocate(address pub_key, uint64 space) internal view {
-        AccountMeta[1] meta = [
-            AccountMeta({pubkey: pub_key, is_signer: true, is_writable: true})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.Allocate), space);
-
-        systemAddress.call{accounts: meta}(bincode);
-    }
-
-    /// Allocate space for an assign an account at an address derived from a base public key and a seed
-    ///
-    /// @param addr account for which to allocate space. It should match create_with_seed(base, seed, owner)
-    /// @param base the base address that derived the 'addr' key using the seed
-    /// @param seed the string utilized to create the 'addr' public key
-    /// @param space number of bytes of memory to allocate
-    /// @param owner owner to use to derive the 'addr' account address
-    function allocate_with_seed(address addr, address base, string seed, uint64 space, address owner) internal view {
-        AccountMeta[2] metas = [
-            AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
-        ];
-
-        bytes bincode = new bytes(seed.length + 84);
-        bincode.writeUint32LE(uint32(Instruction.AllocateWithSeed), 0);
-        bincode.writeAddress(base, 4);
-        bincode.writeUint64LE(seed.length, 36);
-        bincode.writeString(seed, 44);
-        uint32 offset = 44 + seed.length;
-        bincode.writeUint64LE(space, offset);
-        offset += 8;
-        bincode.writeAddress(owner, offset);
-
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Create a new nonce account on Solana using a public key derived from a seed
-    ///
-    /// @param from public key for the account from which to transfer lamports to the new account
-    /// @param nonce the public key for the account to be created. The public key must match create_with_seed(base, seed, systemAddress)
-    /// @param base the base address that derived the 'nonce' key using the seed
-    /// @param seed the string utilized to create the 'addr' public key
-    /// @param authority The entity authorized to execute nonce instructions on the account
-    /// @param lamports amount of lamports to be transfered to the new account
-    function create_nonce_account_with_seed(address from, address nonce, address base, string seed, address authority, uint64 lamports) internal view {
-        create_account_with_seed(from, nonce, base, seed, lamports, state_size, systemAddress);
-
-        AccountMeta[3] metas = [
-            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
-            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.InitializeNonceAccount), authority);
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Create a new account on Solana
-    ///
-    /// @param from public key for the account from which to transfer lamports to the new account
-    /// @param nonce the public key for the nonce account to be created
-    /// @param authority The entity authorized to execute nonce instructions on the account
-    /// @param lamports amount of lamports to be transfered to the new account
-    function create_nonce_account(address from, address nonce, address authority, uint64 lamports) internal view {
-        create_account(from, nonce, lamports, state_size, systemAddress);
-
-        AccountMeta[3] metas = [
-            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
-            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.InitializeNonceAccount), authority);
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Consumes a stored nonce, replacing it with a successor
-    ///
-    /// @param nonce_pubkey the public key for the nonce account
-    /// @param authorized_pubkey the publick key for the entity authorized to execute instructins on the account
-    function advance_nonce_account(address nonce_pubkey, address authorized_pubkey) internal view {
-        AccountMeta[3] metas = [
-            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
-            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.AdvanceNounceAccount));
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Withdraw funds from a nonce account
-    ///
-    /// @param nonce_pubkey the public key for the nonce account
-    /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
-    /// @param to_pubkey the recipient account
-    /// @param lamports the number of lamports to withdraw
-    function withdraw_nonce_account(address nonce_pubkey, address authorized_pubkey, address to_pubkey, uint64 lamports) internal view {
-        AccountMeta[5] metas = [
-            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: to_pubkey, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
-            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false}),
-            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.WithdrawNonceAccount), lamports);
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// Change the entity authorized to execute nonce instructions on the account
-    ///
-    /// @param nonce_pubkey the public key for the nonce account
-    /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
-    /// @param new_authority
-    function authorize_nonce_account(address nonce_pubkey, address authorized_pubkey, address new_authority) internal view {
-        AccountMeta[2] metas = [
-            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
-            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.AuthorizeNonceAccount), new_authority);
-        systemAddress.call{accounts: metas}(bincode);
-    }
-
-    /// One-time idempotent upgrade of legacy nonce version in order to bump them out of chain domain.
-    ///
-    /// @param nonce the public key for the nonce account
-    // This is not available on Solana v1.9.15
-    function upgrade_nonce_account(address nonce) internal view {
-        AccountMeta[1] meta = [
-            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true})
-        ];
-
-        bytes bincode = abi.encode(uint32(Instruction.UpgradeNonceAccount));
-        systemAddress.call{accounts: meta}(bincode);
-    }
-}

+ 30 - 31
tokens/spl-token-minter/solang/tests/spl-token-minter.ts

@@ -1,51 +1,51 @@
-import * as anchor from "@coral-xyz/anchor"
-import { Program } from "@coral-xyz/anchor"
-import { SplTokenMinter } from "../target/types/spl_token_minter"
-import { PublicKey, SystemProgram, SYSVAR_RENT_PUBKEY } from "@solana/web3.js"
-import { Metaplex } from "@metaplex-foundation/js"
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { SplTokenMinter } from "../target/types/spl_token_minter";
+import { PublicKey, SystemProgram, SYSVAR_RENT_PUBKEY } from "@solana/web3.js";
+import { Metaplex } from "@metaplex-foundation/js";
 import {
   ASSOCIATED_TOKEN_PROGRAM_ID,
   getOrCreateAssociatedTokenAccount,
   TOKEN_PROGRAM_ID,
-} from "@solana/spl-token"
+} from "@solana/spl-token";
 
 describe("spl-token-minter", () => {
   // Configure the client to use the local cluster.
-  const provider = anchor.AnchorProvider.env()
-  anchor.setProvider(provider)
+  const provider = anchor.AnchorProvider.env();
+  anchor.setProvider(provider);
 
   // Generate a new keypair for the data account for the program
-  const dataAccount = anchor.web3.Keypair.generate()
+  const dataAccount = anchor.web3.Keypair.generate();
   // Generate a mint keypair
-  const mintKeypair = anchor.web3.Keypair.generate()
-  const wallet = provider.wallet as anchor.Wallet
-  const connection = provider.connection
+  const mintKeypair = anchor.web3.Keypair.generate();
+  const wallet = provider.wallet as anchor.Wallet;
+  const connection = provider.connection;
 
-  const program = anchor.workspace.SplTokenMinter as Program<SplTokenMinter>
+  const program = anchor.workspace.SplTokenMinter as Program<SplTokenMinter>;
 
   // Metadata for the Token
-  const tokenTitle = "Solana Gold"
-  const tokenSymbol = "GOLDSOL"
+  const tokenTitle = "Solana Gold";
+  const tokenSymbol = "GOLDSOL";
   const tokenUri =
-    "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json"
+    "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json";
 
   it("Is initialized!", async () => {
     // Initialize data account for the program, which is required by Solang
     const tx = await program.methods
-      .new(wallet.publicKey)
+      .new()
       .accounts({ dataAccount: dataAccount.publicKey })
       .signers([dataAccount])
-      .rpc()
-    console.log("Your transaction signature", tx)
-  })
+      .rpc();
+    console.log("Your transaction signature", tx);
+  });
 
   it("Create an SPL Token!", async () => {
     // Get the metadata address for the mint
-    const metaplex = Metaplex.make(connection)
+    const metaplex = Metaplex.make(connection);
     const metadataAddress = await metaplex
       .nfts()
       .pdas()
-      .metadata({ mint: mintKeypair.publicKey })
+      .metadata({ mint: mintKeypair.publicKey });
 
     // Create the token mint
     const tx = await program.methods
@@ -78,9 +78,9 @@ describe("spl-token-minter", () => {
         { pubkey: SYSVAR_RENT_PUBKEY, isWritable: false, isSigner: false },
       ])
       .signers([mintKeypair])
-      .rpc({ skipPreflight: true })
-    console.log("Your transaction signature", tx)
-  })
+      .rpc({ skipPreflight: true });
+    console.log("Your transaction signature", tx);
+  });
 
   it("Mint some tokens to your wallet!", async () => {
     // Wallet's associated token account address for mint
@@ -89,14 +89,13 @@ describe("spl-token-minter", () => {
       wallet.payer, // payer
       mintKeypair.publicKey, // mint
       wallet.publicKey // owner
-    )
+    );
 
     const tx = await program.methods
       .mintTo(
         wallet.publicKey, // payer
         tokenAccount.address, // associated token account address
         mintKeypair.publicKey, // mint
-        wallet.publicKey, // owner of token account
         new anchor.BN(150) // amount to mint
       )
       .accounts({ dataAccount: dataAccount.publicKey })
@@ -120,7 +119,7 @@ describe("spl-token-minter", () => {
           isSigner: false,
         },
       ])
-      .rpc({ skipPreflight: true })
-    console.log("Your transaction signature", tx)
-  })
-})
+      .rpc({ skipPreflight: true });
+    console.log("Your transaction signature", tx);
+  });
+});

+ 9 - 9
tokens/spl-token-minter/solang/tsconfig.json

@@ -1,11 +1,11 @@
 {
-            "compilerOptions": {
-              "types": ["mocha", "chai"],
-              "typeRoots": ["./node_modules/@types"],
-              "lib": ["es2015"],
-              "module": "commonjs",
-              "target": "es6",
-              "esModuleInterop": true
-            }
-          }
+  "compilerOptions": {
+    "types": ["mocha", "chai"],
+    "typeRoots": ["./node_modules/@types"],
+    "lib": ["es2015"],
+    "module": "commonjs",
+    "target": "es6",
+    "esModuleInterop": true
+  }
+}
           

+ 134 - 0
tokens/transfer-tokens/solang/libraries/mpl_metadata.sol

@@ -0,0 +1,134 @@
+import 'solana';
+
+// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/instruction/metadata.rs#L449
+// Solidity does not support Rust Option<> type, so we need to handle it manually
+// Requires creating a struct for each combination of Option<> types
+// If bool for Option<> type is false, comment out the corresponding struct field otherwise instruction fails with "invalid account data"
+// TODO: figure out better way to handle Option<> types
+library MplMetadata {
+	address constant metadataProgramId = address"metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s";
+	address constant systemAddress = address"11111111111111111111111111111111";
+    address constant rentAddress = address"SysvarRent111111111111111111111111111111111";
+
+	// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/instruction/metadata.rs#L31
+	struct CreateMetadataAccountArgsV3 {
+        DataV2 data;
+        bool isMutable;
+        bool collectionDetailsPresent; // To handle Rust Option<> in Solidity
+        // CollectionDetails collectionDetails;
+    }
+
+	// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/state/data.rs#L22
+    struct DataV2 {
+        string name;
+        string symbol;
+        string uri;
+        uint16 sellerFeeBasisPoints;
+        bool creatorsPresent; // To handle Rust Option<> in Solidity
+        // Creator[] creators;
+        bool collectionPresent; // To handle Rust Option<> in Solidity
+        // Collection collection;
+        bool usesPresent; // To handle Rust Option<> in Solidity
+        // Uses uses;
+    }
+
+	// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/state/metaplex_adapter.rs#L10
+    struct Creator {
+        address creatorAddress;
+        bool verified;
+        uint8 share;
+    }
+
+	// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/state/metaplex_adapter.rs#L66
+    struct Collection {
+        bool verified;
+        address key;
+    }
+
+	// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/state/collection.rs#L57
+    struct CollectionDetails {
+        CollectionDetailsType detailType;
+        uint64 size;
+    }
+    enum CollectionDetailsType {
+        V1
+    }
+
+	// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/state/metaplex_adapter.rs#L43
+    struct Uses {
+        UseMethod useMethod;
+        uint64 remaining;
+        uint64 total;
+    }
+
+	// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/state/metaplex_adapter.rs#L35
+    enum UseMethod {
+        Burn,
+        Multiple,
+        Single
+    }
+
+	function create_metadata_account(
+		address metadata,
+		address mint,
+		address mintAuthority,
+		address payer,
+		address updateAuthority,
+		string name,
+		string symbol,
+		string uri
+	) public {
+        // // Example of how to add a Creator[] array to the DataV2 struct
+		// Creator[] memory creators = new Creator[](1);
+        // creators[0] = Creator({
+        //     creatorAddress: payer,
+        //     verified: false,
+        //     share: 100
+        // });
+
+        DataV2 data = DataV2({
+            name: name,
+            symbol: symbol,
+            uri: uri,
+            sellerFeeBasisPoints: 0,
+            creatorsPresent: false,
+             // creators: creators,
+            collectionPresent: false,
+            // collection: Collection({
+            //     verified: false,
+            //     key: address(0)
+            // }),
+            usesPresent: false
+            // uses: Uses({
+            //     useMethod: UseMethod.Burn,
+            //     remaining: 0,
+            //     total: 0
+            // })
+        });
+
+        CreateMetadataAccountArgsV3 args = CreateMetadataAccountArgsV3({
+            data: data,
+            isMutable: true,
+            collectionDetailsPresent: false
+			// collectionDetails: CollectionDetails({
+            //     detailType: CollectionDetailsType.V1,
+            //     size: 0
+            // })
+        });
+
+        AccountMeta[7] metas = [
+            AccountMeta({pubkey: metadata, is_writable: true, is_signer: false}),
+            AccountMeta({pubkey: mint, is_writable: false, is_signer: false}),
+            AccountMeta({pubkey: mintAuthority, is_writable: false, is_signer: true}),
+            AccountMeta({pubkey: payer, is_writable: true, is_signer: true}),
+            AccountMeta({pubkey: updateAuthority, is_writable: false, is_signer: false}),
+            AccountMeta({pubkey: systemAddress, is_writable: false, is_signer: false}),
+            AccountMeta({pubkey: rentAddress, is_writable: false, is_signer: false})
+        ];
+
+        bytes1 discriminator = 33;
+        bytes instructionData = abi.encode(discriminator, args);
+
+        metadataProgramId.call{accounts: metas}(instructionData);
+    }
+}

+ 387 - 0
tokens/transfer-tokens/solang/libraries/spl_token.sol

@@ -0,0 +1,387 @@
+import 'solana';
+import 'system_instruction.sol';
+
+library SplToken {
+	address constant tokenProgramId = address"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
+	address constant associatedTokenProgramId = address"ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
+	address constant rentAddress = address"SysvarRent111111111111111111111111111111111";
+	enum TokenInstruction {
+		InitializeMint, // 0
+		InitializeAccount, // 1
+		InitializeMultisig, // 2
+		Transfer, // 3
+		Approve, // 4
+		Revoke, // 5
+		SetAuthority, // 6
+		MintTo, // 7
+		Burn, // 8
+		CloseAccount, // 9
+		FreezeAccount, // 10
+		ThawAccount, // 11
+		TransferChecked, // 12
+		ApproveChecked, // 13
+		MintToChecked, // 14
+		BurnChecked, // 15
+		InitializeAccount2, // 16
+		SyncNative, // 17
+		InitializeAccount3, // 18
+		InitializeMultisig2, // 19
+		InitializeMint2, // 20
+		GetAccountDataSize, // 21
+		InitializeImmutableOwner, // 22
+		AmountToUiAmount, // 23
+		UiAmountToAmount, // 24
+		InitializeMintCloseAuthority, // 25
+		TransferFeeExtension, // 26
+		ConfidentialTransferExtension, // 27
+		DefaultAccountStateExtension, // 28
+		Reallocate, // 29
+		MemoTransferExtension, // 30
+		CreateNativeMint // 31
+	}
+
+	/// Initialize a new token account.
+	///
+	/// @param tokenAccount the public key of the token account to initialize
+	/// @param mint the public key of the mint account for this new token account
+	/// @param owner the public key of the owner of this new token account
+	function initialize_account(address tokenAccount, address mint, address owner) internal{
+		bytes instr = new bytes(1);
+
+		instr[0] = uint8(TokenInstruction.InitializeAccount);
+		AccountMeta[4] metas = [
+			AccountMeta({pubkey: tokenAccount, is_writable: true, is_signer: false}),
+			AccountMeta({pubkey: mint, is_writable: false, is_signer: false}),
+			AccountMeta({pubkey: owner, is_writable: false, is_signer: false}),
+			AccountMeta({pubkey: rentAddress, is_writable: false, is_signer: false})
+		];
+
+		tokenProgramId.call{accounts: metas}(instr);
+	}
+
+	/// Initialize a new associated token account.
+	///
+	/// @param payer the public key of the payer to create the associated token account
+	/// @param tokenAccount the public key of the token account to initialize
+	/// @param mint the public key of the mint account for this new token account
+	/// @param owner the public key of the owner of this new token account
+    function create_associated_token_account(address payer, address tokenAccount, address mint, address owner) internal {
+        AccountMeta[6] metas = [
+			AccountMeta({pubkey: payer, is_writable: true, is_signer: true}),
+			AccountMeta({pubkey: tokenAccount, is_writable: true, is_signer: false}),
+			AccountMeta({pubkey: owner, is_writable: false, is_signer: false}),
+			AccountMeta({pubkey: mint, is_writable: false, is_signer: false}),
+			AccountMeta({pubkey: SystemInstruction.systemAddress, is_writable: false, is_signer: false}),
+			AccountMeta({pubkey: SplToken.tokenProgramId, is_writable: false, is_signer: false})
+		];
+
+        bytes instructionData = abi.encode((0));
+		associatedTokenProgramId.call{accounts: metas}(instructionData);
+    }
+
+	// Initialize mint instruction data
+	struct InitializeMintInstruction {
+        uint8 instruction;
+        uint8 decimals;
+        address mintAuthority;
+        uint8 freezeAuthorityOption;
+        address freezeAuthority;
+    }
+
+	/// Initialize a new mint account.
+	///
+	/// @param mint the public key of the mint account to initialize
+	/// @param mintAuthority the public key of the mint authority
+	/// @param freezeAuthority the public key of the freeze authority
+	/// @param decimals the decimals of the mint
+	function initialize_mint(address mint, address mintAuthority, address freezeAuthority, uint8 decimals) internal {
+    	InitializeMintInstruction instr = InitializeMintInstruction({
+            instruction: 20,
+            decimals: decimals,
+            mintAuthority: mintAuthority,
+            freezeAuthorityOption: 1,
+            freezeAuthority: freezeAuthority
+        });
+
+		AccountMeta[1] metas = [
+			AccountMeta({pubkey: mint, is_writable: true, is_signer: false})
+		];
+
+		tokenProgramId.call{accounts: metas}(instr);
+	}
+
+	/// Create and initialize a new mint account in one instruction
+	///
+	/// @param payer the public key of the account paying to create the mint account
+	/// @param mint the public key of the mint account to initialize
+	/// @param mintAuthority the public key of the mint authority
+	/// @param freezeAuthority the public key of the freeze authority
+	/// @param decimals the decimals of the mint
+	function create_mint(address payer, address mint, address mintAuthority, address freezeAuthority, uint8 decimals) internal {
+		// Invoke System Program to create a new account for the mint account
+        // Program owner is set to the Token program
+        SystemInstruction.create_account(
+            payer,   // lamports sent from this account (payer)
+            mint,    // lamports sent to this account (account to be created)
+            1461600, // lamport amount (minimum lamports for mint account)
+            82,      // space required for the account (mint account)
+            SplToken.tokenProgramId // new program owner
+        );
+
+		InitializeMintInstruction instr = InitializeMintInstruction({
+            instruction: 20,
+            decimals: decimals,
+            mintAuthority: mintAuthority,
+            freezeAuthorityOption: 1,
+            freezeAuthority: freezeAuthority
+        });
+
+		AccountMeta[1] metas = [
+			AccountMeta({pubkey: mint, is_writable: true, is_signer: false})
+		];
+
+		tokenProgramId.call{accounts: metas}(instr);
+	}
+
+	/// Mint new tokens. The transaction should be signed by the mint authority keypair
+	///
+	/// @param mint the account of the mint
+	/// @param account the token account where the minted tokens should go
+	/// @param authority the public key of the mint authority
+	/// @param amount the amount of tokens to mint
+	function mint_to(address mint, address account, address authority, uint64 amount) internal {
+		bytes instr = new bytes(9);
+
+		instr[0] = uint8(TokenInstruction.MintTo);
+		instr.writeUint64LE(amount, 1);
+
+		AccountMeta[3] metas = [
+			AccountMeta({pubkey: mint, is_writable: true, is_signer: false}),
+			AccountMeta({pubkey: account, is_writable: true, is_signer: false}),
+			AccountMeta({pubkey: authority, is_writable: true, is_signer: true})
+		];
+
+		tokenProgramId.call{accounts: metas}(instr);
+	}
+
+	/// Transfer @amount token from @from to @to. The transaction should be signed by the owner
+	/// keypair of the from account.
+	///
+	/// @param from the account to transfer tokens from
+	/// @param to the account to transfer tokens to
+	/// @param owner the publickey of the from account owner keypair
+	/// @param amount the amount to transfer
+	function transfer(address from, address to, address owner, uint64 amount) internal {
+		bytes instr = new bytes(9);
+
+		instr[0] = uint8(TokenInstruction.Transfer);
+		instr.writeUint64LE(amount, 1);
+
+		AccountMeta[3] metas = [
+			AccountMeta({pubkey: from, is_writable: true, is_signer: false}),
+			AccountMeta({pubkey: to, is_writable: true, is_signer: false}),
+			AccountMeta({pubkey: owner, is_writable: true, is_signer: true})
+		];
+
+		tokenProgramId.call{accounts: metas}(instr);
+	}
+
+	/// Burn @amount tokens in account. This transaction should be signed by the owner.
+	///
+	/// @param account the acount for which tokens should be burned
+	/// @param mint the mint for this token
+	/// @param owner the publickey of the account owner keypair
+	/// @param amount the amount to transfer
+	function burn(address account, address mint, address owner, uint64 amount) internal {
+		bytes instr = new bytes(9);
+
+		instr[0] = uint8(TokenInstruction.Burn);
+		instr.writeUint64LE(amount, 1);
+
+		AccountMeta[3] metas = [
+			AccountMeta({pubkey: account, is_writable: true, is_signer: false}),
+			AccountMeta({pubkey: mint, is_writable: true, is_signer: false}),
+			AccountMeta({pubkey: owner, is_writable: true, is_signer: true})
+		];
+
+		tokenProgramId.call{accounts: metas}(instr);
+	}
+
+	/// Approve an amount to a delegate. This transaction should be signed by the owner
+	///
+	/// @param account the account for which a delegate should be approved
+	/// @param delegate the delegate publickey
+	/// @param owner the publickey of the account owner keypair
+	/// @param amount the amount to approve
+	function approve(address account, address delegate, address owner, uint64 amount) internal {
+		bytes instr = new bytes(9);
+
+		instr[0] = uint8(TokenInstruction.Approve);
+		instr.writeUint64LE(amount, 1);
+
+		AccountMeta[3] metas = [
+			AccountMeta({pubkey: account, is_writable: true, is_signer: false}),
+			AccountMeta({pubkey: delegate, is_writable: false, is_signer: false}),
+			AccountMeta({pubkey: owner, is_writable: false, is_signer: true})
+		];
+
+		tokenProgramId.call{accounts: metas}(instr);
+	}
+
+	/// Revoke a previously approved delegate. This transaction should be signed by the owner. After
+	/// this transaction, no delgate is approved for any amount.
+	///
+	/// @param account the account for which a delegate should be approved
+	/// @param owner the publickey of the account owner keypair
+	function revoke(address account, address owner) internal {
+		bytes instr = new bytes(1);
+
+		instr[0] = uint8(TokenInstruction.Revoke);
+
+		AccountMeta[2] metas = [
+			AccountMeta({pubkey: account, is_writable: true, is_signer: false}),
+			AccountMeta({pubkey: owner, is_writable: false, is_signer: true})
+		];
+
+		tokenProgramId.call{accounts: metas}(instr);
+	}
+
+	/// Get the total supply for the mint, i.e. the total amount in circulation
+	/// @param mint the mint for this token
+	function total_supply(address mint) internal view returns (uint64) {
+		AccountInfo account = get_account_info(mint);
+
+		return account.data.readUint64LE(36);
+	}
+
+	/// Get the balance for an account.
+	///
+	/// @param account the account for which we want to know a balance
+	function get_balance(address account) internal view returns (uint64) {
+		AccountInfo ai = get_account_info(account);
+
+		return ai.data.readUint64LE(64);
+	}
+
+	/// Get the account info for an account. This walks the transaction account infos
+	/// and find the account info, or the transaction fails.
+	///
+	/// @param account the account for which we want to have the acount info.
+	function get_account_info(address account) internal view returns (AccountInfo) {
+		for (uint64 i = 0; i < tx.accounts.length; i++) {
+			AccountInfo ai = tx.accounts[i];
+			if (ai.key == account) {
+				return ai;
+			}
+		}
+
+		revert("account missing");
+	}
+
+	/// This enum represents the state of a token account
+	enum AccountState {
+		Uninitialized,
+		Initialized,
+		Frozen
+	}
+
+	/// This struct is the return of 'get_token_account_data'
+	struct TokenAccountData {
+		address mintAccount;
+		address owner;
+		uint64 balance;
+		bool delegate_present;
+		address delegate;
+		AccountState state;
+		bool is_native_present;
+		uint64 is_native;
+		uint64 delegated_amount;
+		bool close_authority_present;
+		address close_authority;
+	}
+
+	/// Fetch the owner, mint account and balance for an associated token account.
+	///
+	/// @param tokenAccount The token account
+	/// @return struct TokenAccountData
+	function get_token_account_data(address tokenAccount) public view returns (TokenAccountData) {
+		AccountInfo ai = get_account_info(tokenAccount);
+
+		TokenAccountData data = TokenAccountData(
+			{
+				mintAccount: ai.data.readAddress(0),
+				owner: ai.data.readAddress(32),
+			 	balance: ai.data.readUint64LE(64),
+				delegate_present: ai.data.readUint32LE(72) > 0,
+				delegate: ai.data.readAddress(76),
+				state: AccountState(ai.data[108]),
+				is_native_present: ai.data.readUint32LE(109) > 0,
+				is_native: ai.data.readUint64LE(113),
+				delegated_amount: ai.data.readUint64LE(121),
+				close_authority_present: ai.data.readUint32LE(129) > 10,
+				close_authority: ai.data.readAddress(133)
+			}
+		);
+
+		return data;
+	}
+
+	// This struct is the return of 'get_mint_account_data'
+	struct MintAccountData {
+		bool authority_present;
+		address mint_authority;
+		uint64 supply;
+		uint8 decimals;
+		bool is_initialized;
+		bool freeze_authority_present;
+		address freeze_authority;
+	}
+
+	/// Retrieve the information saved in a mint account
+	///
+	/// @param mintAccount the account whose information we want to retrive
+	/// @return the MintAccountData struct
+	function get_mint_account_data(address mintAccount) public view returns (MintAccountData) {
+		AccountInfo ai = get_account_info(mintAccount);
+
+		uint32 authority_present = ai.data.readUint32LE(0);
+		uint32 freeze_authority_present = ai.data.readUint32LE(46);
+		MintAccountData data = MintAccountData( {
+			authority_present: authority_present > 0,
+			mint_authority: ai.data.readAddress(4),
+			supply: ai.data.readUint64LE(36),
+			decimals: uint8(ai.data[44]),
+			is_initialized: ai.data[45] > 0,
+			freeze_authority_present: freeze_authority_present > 0,
+			freeze_authority: ai.data.readAddress(50)
+		});
+
+		return data;
+	}
+
+	// A mint account has an authority, whose type is one of the members of this struct.
+	enum AuthorityType {
+		MintTokens,
+		FreezeAccount,
+		AccountOwner,
+		CloseAccount
+	}
+
+	/// Remove the mint authority from a mint account
+	///
+	/// @param mintAccount the public key for the mint account
+	/// @param mintAuthority the public for the mint authority
+	function remove_mint_authority(address mintAccount, address mintAuthority) public {
+		AccountMeta[2] metas = [
+			AccountMeta({pubkey: mintAccount, is_signer: false, is_writable: true}),
+			AccountMeta({pubkey: mintAuthority, is_signer: true, is_writable: false})
+		];
+
+		bytes data = new bytes(9);
+		data[0] = uint8(TokenInstruction.SetAuthority);
+		data[1] = uint8(AuthorityType.MintTokens);
+		data[3] = 0;
+
+		tokenProgramId.call{accounts: metas}(data);
+	}
+}

+ 300 - 0
tokens/transfer-tokens/solang/libraries/system_instruction.sol

@@ -0,0 +1,300 @@
+// SPDX-License-Identifier: Apache-2.0
+
+// Disclaimer: This library provides a bridge for Solidity to interact with Solana's system instructions. Although it is production ready,
+// it has not been audited for security, so use it at your own risk.
+
+import 'solana';
+
+library SystemInstruction {
+    address constant systemAddress = address"11111111111111111111111111111111";
+    address constant recentBlockHashes = address"SysvarRecentB1ockHashes11111111111111111111";
+    address constant rentAddress = address"SysvarRent111111111111111111111111111111111";
+    uint64 constant state_size = 80;
+
+    enum Instruction {
+        CreateAccount,
+        Assign,
+        Transfer,
+        CreateAccountWithSeed,
+        AdvanceNounceAccount,
+        WithdrawNonceAccount,
+        InitializeNonceAccount,
+        AuthorizeNonceAccount,
+        Allocate,
+        AllocateWithSeed,
+        AssignWithSeed,
+        TransferWithSeed,
+        UpgradeNonceAccount // This is not available on Solana v1.9.15
+    }
+
+    /// Create a new account on Solana
+    ///
+    /// @param from public key for the account from which to transfer lamports to the new account
+    /// @param to public key for the account to be created
+    /// @param lamports amount of lamports to be transfered to the new account
+    /// @param space the size in bytes that is going to be made available for the account
+    /// @param owner public key for the program that will own the account being created
+    function create_account(address from, address to, uint64 lamports, uint64 space, address owner) internal {
+        AccountMeta[2] metas = [
+            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
+            AccountMeta({pubkey: to, is_signer: true, is_writable: true})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.CreateAccount), lamports, space, owner);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Create a new account on Solana using a public key derived from a seed
+    ///
+    /// @param from public key for the account from which to transfer lamports to the new account
+    /// @param to the public key for the account to be created. The public key must match create_with_seed(base, seed, owner)
+    /// @param base the base address that derived the 'to' address using the seed
+    /// @param seed the string utilized to created the 'to' public key
+    /// @param lamports amount of lamports to be transfered to the new account
+    /// @param space the size in bytes that is going to be made available for the account
+    /// @param owner public key for the program that will own the account being created
+    function create_account_with_seed(address from, address to, address base, string seed, uint64 lamports, uint64 space, address owner) internal {
+        AccountMeta[3] metas = [
+            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
+            AccountMeta({pubkey: to, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
+        ];
+
+        uint32 buffer_size = 92 + seed.length;
+        bytes bincode = new bytes(buffer_size);
+        bincode.writeUint32LE(uint32(Instruction.CreateAccountWithSeed), 0);
+        bincode.writeAddress(base, 4);
+        bincode.writeUint64LE(uint64(seed.length), 36);
+        bincode.writeString(seed, 44);
+        uint32 offset = seed.length + 44;
+        bincode.writeUint64LE(lamports, offset);
+        offset += 8;
+        bincode.writeUint64LE(space, offset);
+        offset += 8;
+        bincode.writeAddress(owner, offset);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Assign account to a program (owner)
+    ///
+    /// @param pubkey the public key for the account whose owner is going to be reassigned
+    /// @param owner the public key for the new account owner
+    function assign(address pubkey, address owner) internal {
+        AccountMeta[1] meta = [
+            AccountMeta({pubkey: pubkey, is_signer: true, is_writable: true})
+        ];
+        bytes bincode = abi.encode(uint32(Instruction.Assign), owner);
+
+        systemAddress.call{accounts: meta}(bincode);
+    }
+
+    /// Assign account to a program (owner) based on a seed
+    ///
+    /// @param addr the public key for the account whose owner is going to be reassigned. The public key must match create_with_seed(base, seed, owner)
+    /// @param base the base address that derived the 'addr' key using the seed
+    /// @param seed the string utilized to created the 'addr' public key
+    /// @param owner the public key for the new program owner
+    function assign_with_seed(address addr, address base, string seed, address owner) internal {
+        AccountMeta[2] metas = [
+            AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
+        ];
+
+
+        uint32 buffer_size = 76 + seed.length;
+        bytes bincode = new bytes(buffer_size);
+        bincode.writeUint32LE(uint32(Instruction.AssignWithSeed), 0);
+        bincode.writeAddress(base, 4);
+        bincode.writeUint64LE(uint64(seed.length), 36);
+        bincode.writeString(seed, 44);
+        bincode.writeAddress(owner, 44 + seed.length);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Transfer lamports between accounts
+    ///
+    /// @param from public key for the funding account
+    /// @param to public key for the recipient account
+    /// @param lamports amount of lamports to transfer
+    function transfer(address from, address to, uint64 lamports) internal {
+        AccountMeta[2] metas = [
+            AccountMeta({pubkey: from, is_signer: true, is_writable: true}),
+            AccountMeta({pubkey: to, is_signer: false, is_writable: true})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.Transfer), lamports);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Transfer lamports from a derived address
+    ///
+    /// @param from_pubkey The funding account public key. It should match create_with_seed(from_base, seed, from_owner)
+    /// @param from_base the base address that derived the 'from_pubkey' key using the seed
+    /// @param seed the string utilized to create the 'from_pubkey' public key
+    /// @param from_owner owner to use to derive the funding account address
+    /// @param to_pubkey the public key for the recipient account
+    /// @param lamports amount of lamports to transfer
+    function transfer_with_seed(address from_pubkey, address from_base, string seed, address from_owner, address to_pubkey, uint64 lamports) internal {
+        AccountMeta[3] metas = [
+            AccountMeta({pubkey: from_pubkey, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: from_base, is_signer: true, is_writable: false}),
+            AccountMeta({pubkey: to_pubkey, is_signer: false, is_writable: true})
+        ];
+
+        uint32 buffer_size = seed.length + 52;
+        bytes bincode = new bytes(buffer_size);
+        bincode.writeUint32LE(uint32(Instruction.TransferWithSeed), 0);
+        bincode.writeUint64LE(lamports, 4);
+        bincode.writeUint64LE(seed.length, 12);
+        bincode.writeString(seed, 20);
+        bincode.writeAddress(from_owner, 20 + seed.length);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Allocate space in a (possibly new) account without funding
+    ///
+    /// @param pub_key account for which to allocate space
+    /// @param space number of bytes of memory to allocate
+    function allocate(address pub_key, uint64 space) internal {
+        AccountMeta[1] meta = [
+            AccountMeta({pubkey: pub_key, is_signer: true, is_writable: true})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.Allocate), space);
+
+        systemAddress.call{accounts: meta}(bincode);
+    }
+
+    /// Allocate space for an assign an account at an address derived from a base public key and a seed
+    ///
+    /// @param addr account for which to allocate space. It should match create_with_seed(base, seed, owner)
+    /// @param base the base address that derived the 'addr' key using the seed
+    /// @param seed the string utilized to create the 'addr' public key
+    /// @param space number of bytes of memory to allocate
+    /// @param owner owner to use to derive the 'addr' account address
+    function allocate_with_seed(address addr, address base, string seed, uint64 space, address owner) internal {
+        AccountMeta[2] metas = [
+            AccountMeta({pubkey: addr, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: base, is_signer: true, is_writable: false})
+        ];
+
+        bytes bincode = new bytes(seed.length + 84);
+        bincode.writeUint32LE(uint32(Instruction.AllocateWithSeed), 0);
+        bincode.writeAddress(base, 4);
+        bincode.writeUint64LE(seed.length, 36);
+        bincode.writeString(seed, 44);
+        uint32 offset = 44 + seed.length;
+        bincode.writeUint64LE(space, offset);
+        offset += 8;
+        bincode.writeAddress(owner, offset);
+
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Create a new nonce account on Solana using a public key derived from a seed
+    ///
+    /// @param from public key for the account from which to transfer lamports to the new account
+    /// @param nonce the public key for the account to be created. The public key must match create_with_seed(base, seed, systemAddress)
+    /// @param base the base address that derived the 'nonce' key using the seed
+    /// @param seed the string utilized to create the 'addr' public key
+    /// @param authority The entity authorized to execute nonce instructions on the account
+    /// @param lamports amount of lamports to be transfered to the new account
+    function create_nonce_account_with_seed(address from, address nonce, address base, string seed, address authority, uint64 lamports) internal {
+        create_account_with_seed(from, nonce, base, seed, lamports, state_size, systemAddress);
+
+        AccountMeta[3] metas = [
+            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
+            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.InitializeNonceAccount), authority);
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Create a new account on Solana
+    ///
+    /// @param from public key for the account from which to transfer lamports to the new account
+    /// @param nonce the public key for the nonce account to be created
+    /// @param authority The entity authorized to execute nonce instructions on the account
+    /// @param lamports amount of lamports to be transfered to the new account
+    function create_nonce_account(address from, address nonce, address authority, uint64 lamports) internal {
+        create_account(from, nonce, lamports, state_size, systemAddress);
+
+        AccountMeta[3] metas = [
+            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
+            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.InitializeNonceAccount), authority);
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Consumes a stored nonce, replacing it with a successor
+    ///
+    /// @param nonce_pubkey the public key for the nonce account
+    /// @param authorized_pubkey the publick key for the entity authorized to execute instructins on the account
+    function advance_nonce_account(address nonce_pubkey, address authorized_pubkey) internal {
+        AccountMeta[3] metas = [
+            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
+            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.AdvanceNounceAccount));
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Withdraw funds from a nonce account
+    ///
+    /// @param nonce_pubkey the public key for the nonce account
+    /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
+    /// @param to_pubkey the recipient account
+    /// @param lamports the number of lamports to withdraw
+    function withdraw_nonce_account(address nonce_pubkey, address authorized_pubkey, address to_pubkey, uint64 lamports) internal {
+        AccountMeta[5] metas = [
+            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: to_pubkey, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: recentBlockHashes, is_signer: false, is_writable: false}),
+            AccountMeta({pubkey: rentAddress, is_signer: false, is_writable: false}),
+            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.WithdrawNonceAccount), lamports);
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// Change the entity authorized to execute nonce instructions on the account
+    ///
+    /// @param nonce_pubkey the public key for the nonce account
+    /// @param authorized_pubkey the public key for the entity authorized to execute instructins on the account
+    /// @param new_authority
+    function authorize_nonce_account(address nonce_pubkey, address authorized_pubkey, address new_authority) internal {
+        AccountMeta[2] metas = [
+            AccountMeta({pubkey: nonce_pubkey, is_signer: false, is_writable: true}),
+            AccountMeta({pubkey: authorized_pubkey, is_signer: true, is_writable: false})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.AuthorizeNonceAccount), new_authority);
+        systemAddress.call{accounts: metas}(bincode);
+    }
+
+    /// One-time idempotent upgrade of legacy nonce version in order to bump them out of chain domain.
+    ///
+    /// @param nonce the public key for the nonce account
+    // This is not available on Solana v1.9.15
+    function upgrade_nonce_account(address nonce) internal {
+        AccountMeta[1] meta = [
+            AccountMeta({pubkey: nonce, is_signer: false, is_writable: true})
+        ];
+
+        bytes bincode = abi.encode(uint32(Instruction.UpgradeNonceAccount));
+        systemAddress.call{accounts: meta}(bincode);
+    }
+}

+ 1 - 0
tokens/transfer-tokens/solang/package.json

@@ -6,6 +6,7 @@
     "dependencies": {
         "@coral-xyz/anchor": "^0.28.0",
         "@metaplex-foundation/js": "^0.19.4",
+        "@project-serum/anchor": "^0.26.0",
         "@solana/spl-token": "^0.3.8"
     },
     "devDependencies": {

+ 0 - 134
tokens/transfer-tokens/solang/solidity/mpl_metadata.sol

@@ -1,134 +0,0 @@
-import 'solana';
-
-// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/instruction/metadata.rs#L449
-// Solidity does not support Rust Option<> type, so we need to handle it manually
-// Requires creating a struct for each combination of Option<> types
-// If bool for Option<> type is false, comment out the corresponding struct field otherwise instruction fails with "invalid account data"
-// TODO: figure out better way to handle Option<> types
-library MplMetadata {
-	address constant metadataProgramId = address"metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s";
-	address constant systemAddress = address"11111111111111111111111111111111";
-    address constant rentAddress = address"SysvarRent111111111111111111111111111111111";
-
-	// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/instruction/metadata.rs#L31
-	struct CreateMetadataAccountArgsV3 {
-        DataV2 data;
-        bool isMutable;
-        bool collectionDetailsPresent; // To handle Rust Option<> in Solidity
-        // CollectionDetails collectionDetails;
-    }
-
-	// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/state/data.rs#L22
-    struct DataV2 {
-        string name;
-        string symbol;
-        string uri;
-        uint16 sellerFeeBasisPoints;
-        bool creatorsPresent; // To handle Rust Option<> in Solidity
-        // Creator[] creators;
-        bool collectionPresent; // To handle Rust Option<> in Solidity
-        // Collection collection;
-        bool usesPresent; // To handle Rust Option<> in Solidity
-        // Uses uses;
-    }
-
-	// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/state/metaplex_adapter.rs#L10
-    struct Creator {
-        address creatorAddress;
-        bool verified;
-        uint8 share;
-    }
-
-	// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/state/metaplex_adapter.rs#L66
-    struct Collection {
-        bool verified;
-        address key;
-    }
-
-	// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/state/collection.rs#L57
-    struct CollectionDetails {
-        CollectionDetailsType detailType;
-        uint64 size;
-    }
-    enum CollectionDetailsType {
-        V1
-    }
-
-	// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/state/metaplex_adapter.rs#L43
-    struct Uses {
-        UseMethod useMethod;
-        uint64 remaining;
-        uint64 total;
-    }
-
-	// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/state/metaplex_adapter.rs#L35
-    enum UseMethod {
-        Burn,
-        Multiple,
-        Single
-    }
-
-	function create_metadata_account(
-		address metadata,
-		address mint,
-		address mintAuthority,
-		address payer,
-		address updateAuthority,
-		string name,
-		string symbol,
-		string uri
-	) public view {
-        // // Example of how to add a Creator[] array to the DataV2 struct
-		// Creator[] memory creators = new Creator[](1);
-        // creators[0] = Creator({
-        //     creatorAddress: payer,
-        //     verified: false,
-        //     share: 100
-        // });
-
-        DataV2 data = DataV2({
-            name: name,
-            symbol: symbol,
-            uri: uri,
-            sellerFeeBasisPoints: 0,
-            creatorsPresent: false,
-             // creators: creators,
-            collectionPresent: false,
-            // collection: Collection({
-            //     verified: false,
-            //     key: address(0)
-            // }),
-            usesPresent: false
-            // uses: Uses({
-            //     useMethod: UseMethod.Burn,
-            //     remaining: 0,
-            //     total: 0
-            // })
-        });
-
-        CreateMetadataAccountArgsV3 args = CreateMetadataAccountArgsV3({
-            data: data,
-            isMutable: true,
-            collectionDetailsPresent: false
-			// collectionDetails: CollectionDetails({
-            //     detailType: CollectionDetailsType.V1,
-            //     size: 0
-            // })
-        });
-
-        AccountMeta[7] metas = [
-            AccountMeta({pubkey: metadata, is_writable: true, is_signer: false}),
-            AccountMeta({pubkey: mint, is_writable: false, is_signer: false}),
-            AccountMeta({pubkey: mintAuthority, is_writable: false, is_signer: true}),
-            AccountMeta({pubkey: payer, is_writable: true, is_signer: true}),
-            AccountMeta({pubkey: updateAuthority, is_writable: false, is_signer: false}),
-            AccountMeta({pubkey: systemAddress, is_writable: false, is_signer: false}),
-            AccountMeta({pubkey: rentAddress, is_writable: false, is_signer: false})
-        ];
-
-        bytes1 discriminator = 33;
-        bytes instructionData = abi.encode(discriminator, args);
-
-        metadataProgramId.call{accounts: metas}(instructionData);
-    }
-}

Some files were not shown because too many files changed in this diff