Skip to content

Commit 7323844

Browse files
committed
solang tokens examples
1 parent 3529ef5 commit 7323844

38 files changed

+4332
-0
lines changed

tokens/create-token/solang/.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
.anchor
3+
.DS_Store
4+
target
5+
**/*.rs.bk
6+
node_modules
7+
test-ledger
8+
.yarn
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
[features]
2+
seeds = false
3+
skip-lint = false
4+
[programs.localnet]
5+
create_token = "8eZPhSaXfHqbcrfskVThtCG68kq8MfVHqmtm6wYf4TLb"
6+
7+
[registry]
8+
url = "https://api.apr.dev"
9+
10+
[provider]
11+
cluster = "Localnet"
12+
wallet = "~/.config/solana/id.json"
13+
14+
[scripts]
15+
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
16+
17+
[test.validator]
18+
url = "https://api.mainnet-beta.solana.com"
19+
20+
[[test.validator.clone]]
21+
address = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"scripts": {
3+
"lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w",
4+
"lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check"
5+
},
6+
"dependencies": {
7+
"@coral-xyz/anchor": "^0.28.0",
8+
"@metaplex-foundation/js": "^0.19.4"
9+
},
10+
"devDependencies": {
11+
"@types/bn.js": "^5.1.0",
12+
"@types/chai": "^4.3.0",
13+
"@types/mocha": "^9.0.0",
14+
"chai": "^4.3.4",
15+
"mocha": "^9.0.3",
16+
"prettier": "^2.6.2",
17+
"ts-mocha": "^10.0.0",
18+
"typescript": "^4.3.5"
19+
}
20+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
2+
import "./spl_token.sol";
3+
import "./mpl_metadata.sol";
4+
5+
@program_id("8eZPhSaXfHqbcrfskVThtCG68kq8MfVHqmtm6wYf4TLb")
6+
contract create_token {
7+
8+
// Creating a dataAccount is required by Solang
9+
// The account is unused in this example
10+
@payer(payer) // payer account
11+
constructor(address payer) {}
12+
13+
function createTokenMint(
14+
address payer, // payer account
15+
address mint, // mint account to be created
16+
address mintAuthority, // mint authority for the mint account
17+
address freezeAuthority, // freeze authority for the mint account
18+
address metadata, // metadata account to be created
19+
uint8 decimals, // decimals for the mint account
20+
string name, // name for the metadata account
21+
string symbol, // symbol for the metadata account
22+
string uri // uri for the metadata account
23+
) public view {
24+
// Invoke System Program to create a new account for the mint account and,
25+
// Invoke Token Program to initialize the mint account
26+
// Set mint authority, freeze authority, and decimals for the mint account
27+
SplToken.create_mint(
28+
payer, // payer account
29+
mint, // mint account
30+
mintAuthority, // mint authority
31+
freezeAuthority, // freeze authority
32+
decimals // decimals
33+
);
34+
35+
// Invoke Metadata Program to create a new account for the metadata account
36+
MplMetadata.create_metadata_account(
37+
metadata, // metadata account
38+
mint, // mint account
39+
mintAuthority, // mint authority
40+
payer, // payer
41+
payer, // update authority (of the metadata account)
42+
name, // name
43+
symbol, // symbol
44+
uri // uri (off-chain metadata json)
45+
);
46+
}
47+
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import 'solana';
2+
3+
// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/instruction/metadata.rs#L449
4+
// Solidity does not support Rust Option<> type, so we need to handle it manually
5+
// Requires creating a struct for each combination of Option<> types
6+
// If bool for Option<> type is false, comment out the corresponding struct field otherwise instruction fails with "invalid account data"
7+
// TODO: figure out better way to handle Option<> types
8+
library MplMetadata {
9+
address constant metadataProgramId = address"metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s";
10+
address constant systemAddress = address"11111111111111111111111111111111";
11+
address constant rentAddress = address"SysvarRent111111111111111111111111111111111";
12+
13+
// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/instruction/metadata.rs#L31
14+
struct CreateMetadataAccountArgsV3 {
15+
DataV2 data;
16+
bool isMutable;
17+
bool collectionDetailsPresent; // To handle Rust Option<> in Solidity
18+
// CollectionDetails collectionDetails;
19+
}
20+
21+
// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/state/data.rs#L22
22+
struct DataV2 {
23+
string name;
24+
string symbol;
25+
string uri;
26+
uint16 sellerFeeBasisPoints;
27+
bool creatorsPresent; // To handle Rust Option<> in Solidity
28+
// Creator[] creators;
29+
bool collectionPresent; // To handle Rust Option<> in Solidity
30+
// Collection collection;
31+
bool usesPresent; // To handle Rust Option<> in Solidity
32+
// Uses uses;
33+
}
34+
35+
// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/state/metaplex_adapter.rs#L10
36+
struct Creator {
37+
address creatorAddress;
38+
bool verified;
39+
uint8 share;
40+
}
41+
42+
// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/state/metaplex_adapter.rs#L66
43+
struct Collection {
44+
bool verified;
45+
address key;
46+
}
47+
48+
// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/state/collection.rs#L57
49+
struct CollectionDetails {
50+
CollectionDetailsType detailType;
51+
uint64 size;
52+
}
53+
enum CollectionDetailsType {
54+
V1
55+
}
56+
57+
// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/state/metaplex_adapter.rs#L43
58+
struct Uses {
59+
UseMethod useMethod;
60+
uint64 remaining;
61+
uint64 total;
62+
}
63+
64+
// Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/state/metaplex_adapter.rs#L35
65+
enum UseMethod {
66+
Burn,
67+
Multiple,
68+
Single
69+
}
70+
71+
function create_metadata_account(
72+
address metadata,
73+
address mint,
74+
address mintAuthority,
75+
address payer,
76+
address updateAuthority,
77+
string name,
78+
string symbol,
79+
string uri
80+
) public view {
81+
// // Example of how to add a Creator[] array to the DataV2 struct
82+
// Creator[] memory creators = new Creator[](1);
83+
// creators[0] = Creator({
84+
// creatorAddress: payer,
85+
// verified: false,
86+
// share: 100
87+
// });
88+
89+
DataV2 data = DataV2({
90+
name: name,
91+
symbol: symbol,
92+
uri: uri,
93+
sellerFeeBasisPoints: 0,
94+
creatorsPresent: false,
95+
// creators: creators,
96+
collectionPresent: false,
97+
// collection: Collection({
98+
// verified: false,
99+
// key: address(0)
100+
// }),
101+
usesPresent: false
102+
// uses: Uses({
103+
// useMethod: UseMethod.Burn,
104+
// remaining: 0,
105+
// total: 0
106+
// })
107+
});
108+
109+
CreateMetadataAccountArgsV3 args = CreateMetadataAccountArgsV3({
110+
data: data,
111+
isMutable: true,
112+
collectionDetailsPresent: false
113+
// collectionDetails: CollectionDetails({
114+
// detailType: CollectionDetailsType.V1,
115+
// size: 0
116+
// })
117+
});
118+
119+
AccountMeta[7] metas = [
120+
AccountMeta({pubkey: metadata, is_writable: true, is_signer: false}),
121+
AccountMeta({pubkey: mint, is_writable: false, is_signer: false}),
122+
AccountMeta({pubkey: mintAuthority, is_writable: false, is_signer: true}),
123+
AccountMeta({pubkey: payer, is_writable: true, is_signer: true}),
124+
AccountMeta({pubkey: updateAuthority, is_writable: false, is_signer: false}),
125+
AccountMeta({pubkey: systemAddress, is_writable: false, is_signer: false}),
126+
AccountMeta({pubkey: rentAddress, is_writable: false, is_signer: false})
127+
];
128+
129+
bytes1 discriminator = 33;
130+
bytes instructionData = abi.encode(discriminator, args);
131+
132+
metadataProgramId.call{accounts: metas}(instructionData);
133+
}
134+
}

0 commit comments

Comments
 (0)