|
@@ -0,0 +1,148 @@
|
|
1
|
+use itertools::Itertools;
|
|
2
|
+use near_account_id::AccountId;
|
|
3
|
+use near_client::{
|
|
4
|
+ client::{NearClient, Signer},
|
|
5
|
+ types::crypto::{ED25519PublicKey, ED25519SecretKey, Key},
|
|
6
|
+};
|
|
7
|
+use rand::{RngCore, SeedableRng};
|
|
8
|
+use rand_chacha::ChaChaRng;
|
|
9
|
+use reqwest::Url;
|
|
10
|
+use serde_json::json;
|
|
11
|
+use std::{
|
|
12
|
+ fs::{create_dir, File},
|
|
13
|
+ io::{copy, Cursor, Read},
|
|
14
|
+ path::Path,
|
|
15
|
+ str::FromStr,
|
|
16
|
+};
|
|
17
|
+use workspaces::{network::Sandbox, types::SecretKey, Worker};
|
|
18
|
+
|
|
19
|
+// auxiliary structs and methods
|
|
20
|
+struct InitMeta {
|
|
21
|
+ worker: Worker<Sandbox>,
|
|
22
|
+ client: NearClient,
|
|
23
|
+ wasm: Vec<u8>,
|
|
24
|
+ signer_account_id: AccountId,
|
|
25
|
+}
|
|
26
|
+
|
|
27
|
+impl InitMeta {
|
|
28
|
+ async fn new() -> anyhow::Result<Self> {
|
|
29
|
+ let worker = workspaces::sandbox().await?;
|
|
30
|
+ let wasm = download_contract().await?;
|
|
31
|
+ let rpc_url = Url::parse(format!("http://localhost:{}", worker.rpc_port()).as_str())?;
|
|
32
|
+ let client = NearClient::new(rpc_url)?;
|
|
33
|
+ let signer_account_id = AccountId::from_str("alice.test.near")?;
|
|
34
|
+
|
|
35
|
+ Ok(InitMeta {
|
|
36
|
+ worker,
|
|
37
|
+ client,
|
|
38
|
+ wasm,
|
|
39
|
+ signer_account_id,
|
|
40
|
+ })
|
|
41
|
+ }
|
|
42
|
+}
|
|
43
|
+
|
|
44
|
+async fn create_signer(meta: &InitMeta) -> anyhow::Result<Signer> {
|
|
45
|
+ let secret_key = ED25519SecretKey::from_bytes(&random_bits())?;
|
|
46
|
+ let ws_secret_key_str = to_workspaces_sk(&secret_key);
|
|
47
|
+ let pk = ED25519PublicKey::from(&secret_key);
|
|
48
|
+ let ws_sk = SecretKey::from_str(&ws_secret_key_str)?;
|
|
49
|
+ let _ = meta
|
|
50
|
+ .worker
|
|
51
|
+ .create_tla(meta.signer_account_id.clone(), ws_sk)
|
|
52
|
+ .await?;
|
|
53
|
+
|
|
54
|
+ let access_key_nonce = meta
|
|
55
|
+ .client
|
|
56
|
+ .view_access_key(&meta.signer_account_id, &pk)
|
|
57
|
+ .await?
|
|
58
|
+ .nonce;
|
|
59
|
+
|
|
60
|
+ let signer_acc = Signer::new(
|
|
61
|
+ &ws_secret_key_str,
|
|
62
|
+ meta.signer_account_id.clone(),
|
|
63
|
+ access_key_nonce,
|
|
64
|
+ )?;
|
|
65
|
+
|
|
66
|
+ Ok(signer_acc)
|
|
67
|
+}
|
|
68
|
+
|
|
69
|
+async fn download_contract() -> anyhow::Result<Vec<u8>> {
|
|
70
|
+ let target = "https://github.com/near-examples/FT/raw/master/res/fungible_token.wasm";
|
|
71
|
+ let target_path = "../target/tmp-contracts";
|
|
72
|
+ let fname = "contract.wasm";
|
|
73
|
+ let full_dest = format!("{}/{}", target_path, fname);
|
|
74
|
+
|
|
75
|
+ if !Path::new(target_path).exists() {
|
|
76
|
+ create_dir(target_path)?;
|
|
77
|
+ }
|
|
78
|
+
|
|
79
|
+ if !Path::new(&full_dest).exists() {
|
|
80
|
+ let response = reqwest::get(target).await?;
|
|
81
|
+ let mut file = File::create(&full_dest)?;
|
|
82
|
+ let mut content = Cursor::new(response.bytes().await?);
|
|
83
|
+ copy(&mut content, &mut file)?;
|
|
84
|
+ }
|
|
85
|
+
|
|
86
|
+ let mut file = File::open(full_dest)?;
|
|
87
|
+ let mut data = Vec::new();
|
|
88
|
+ file.read_to_end(&mut data)?;
|
|
89
|
+
|
|
90
|
+ Ok(data)
|
|
91
|
+}
|
|
92
|
+
|
|
93
|
+fn random_bits() -> [u8; 32] {
|
|
94
|
+ let mut chacha = ChaChaRng::from_entropy();
|
|
95
|
+ let mut secret_bytes = [0_u8; 32];
|
|
96
|
+ chacha.fill_bytes(&mut secret_bytes);
|
|
97
|
+ secret_bytes
|
|
98
|
+}
|
|
99
|
+
|
|
100
|
+fn to_workspaces_sk(sk: &ED25519SecretKey) -> String {
|
|
101
|
+ let pk = ED25519PublicKey::from(sk);
|
|
102
|
+ let keypair = sk
|
|
103
|
+ .as_bytes()
|
|
104
|
+ .iter()
|
|
105
|
+ .chain(pk.as_bytes().iter())
|
|
106
|
+ .copied()
|
|
107
|
+ .collect_vec();
|
|
108
|
+ format!("ed25519:{}", bs58::encode(keypair).into_string())
|
|
109
|
+}
|
|
110
|
+
|
|
111
|
+// tests themselves
|
|
112
|
+#[tokio::test]
|
|
113
|
+async fn contract_creation() -> anyhow::Result<()> {
|
|
114
|
+ let meta = InitMeta::new().await?;
|
|
115
|
+ let mut signer = create_signer(&meta).await?;
|
|
116
|
+
|
|
117
|
+ let call = meta
|
|
118
|
+ .client
|
|
119
|
+ .deploy_contract(&mut signer, &meta.signer_account_id, meta.wasm);
|
|
120
|
+
|
|
121
|
+ call.commit_empty().await?;
|
|
122
|
+
|
|
123
|
+ Ok(())
|
|
124
|
+}
|
|
125
|
+
|
|
126
|
+#[tokio::test]
|
|
127
|
+async fn contract_function_call() -> anyhow::Result<()> {
|
|
128
|
+ let meta = InitMeta::new().await?;
|
|
129
|
+ let mut signer = create_signer(&meta).await?;
|
|
130
|
+
|
|
131
|
+ let call = meta
|
|
132
|
+ .client
|
|
133
|
+ .deploy_contract(&mut signer, &meta.signer_account_id, meta.wasm);
|
|
134
|
+ call.commit_empty().await?;
|
|
135
|
+
|
|
136
|
+ let call = meta
|
|
137
|
+ .client
|
|
138
|
+ .function_call(&mut signer, &meta.signer_account_id, "new_default_meta")
|
|
139
|
+ .args(json!({
|
|
140
|
+ "owner_id": &meta.signer_account_id,
|
|
141
|
+ "total_supply": "100",
|
|
142
|
+ }))
|
|
143
|
+ .gas(near_units::parse_gas!("300 T") as u64)
|
|
144
|
+ .build()?;
|
|
145
|
+ call.commit_empty().await?;
|
|
146
|
+
|
|
147
|
+ Ok(())
|
|
148
|
+}
|