-
Notifications
You must be signed in to change notification settings - Fork 92
/
index.js
181 lines (157 loc) · 7.36 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
const fs = require('fs');
const yargs = require('yargs');
const ncp = require('ncp').ncp;
ncp.limit = 16;
const rimraf = require('rimraf');
const readline = require('readline');
const URL = require('url').URL;
const chalk = require('chalk'); // colorize output
const open = require('open'); // open URL in default browser
const { KeyPair, utils } = require('nearlib');
const connect = require('./utils/connect');
const verify = require('./utils/verify-account');
const capture = require('./utils/capture-login-success');
const inspectResponse = require('./utils/inspect-response');
// TODO: Fix promisified wrappers to handle error properly
// For smart contract:
exports.clean = async function() {
const rmDirFn = () => {
return new Promise(resolve => {
rimraf(yargs.argv.outDir, response => resolve(response));
});};
await rmDirFn();
console.log('Clean complete.');
};
exports.deploy = async function(options) {
console.log(
`Starting deployment. Account id: ${options.accountId}, node: ${options.nodeUrl}, helper: ${options.helperUrl}, file: ${options.wasmFile}`);
const near = await connect(options);
const contractData = [...fs.readFileSync(options.wasmFile)];
const account = await near.account(options.accountId);
await account.deployContract(contractData);
};
exports.callViewFunction = async function(options) {
console.log(`View call: ${options.contractName}.${options.methodName}(${options.args || ''})`);
const near = await connect(options);
// TODO: Figure out how to run readonly calls without account
const account = await near.account(options.accountId || options.masterAccount || 'register.near');
console.log(inspectResponse(await account.viewFunction(options.contractName, options.methodName, JSON.parse(options.args || '{}'))));
};
// For account:
exports.login = async function(options) {
if (!options.walletUrl) {
console.log('Log in is not needed on this environment. Please use appropriate master account for shell operations.');
} else {
const newUrl = new URL(options.walletUrl + '/login/');
const title = 'NEAR Shell';
newUrl.searchParams.set('title', title);
const keyPair = await KeyPair.fromRandom('ed25519');
newUrl.searchParams.set('public_key', keyPair.getPublicKey());
console.log(chalk`\n{bold.yellow Please authorize NEAR Shell} on at least one of your accounts.`);
// attempt to capture accountId automatically via browser callback
let tempUrl;
// find a callback URL on the local machine
try {
tempUrl = await capture.callback();
} catch (error) {
// console.error("Failed to find suitable port.", error.message)
// TODO: Is it? Try triggering error
// silent error is better here
}
// if we found a suitable URL, attempt to use it
if (tempUrl) {
if (process.env.GITPOD_WORKSPACE_URL) {
const workspaceUrl = new URL(process.env.GITPOD_WORKSPACE_URL);
newUrl.searchParams.set('success_url', `https://${tempUrl.port}-${workspaceUrl.hostname}`);
} else {
newUrl.searchParams.set('success_url', `http://${tempUrl.hostname}:${tempUrl.port}`);
}
try {
// open a browser to capture NEAR Wallet callback (and quietly direct the user if open fails)
await open(newUrl.toString());
} catch (error) {
console.error(`Failed to open the URL [ ${newUrl.toString()} ]`, error);
}
}
console.log(chalk`\n{dim If your browser doesn't automatically open, please visit this URL\n${newUrl.toString()}}`);
const getAccountFromWebpage = async () => {
// capture account_id as provided by NEAR Wallet
const [accountId] = await capture.payload(['account_id'], tempUrl);
return accountId;
};
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const getAccountFromConsole = async () => {
return await new Promise((resolve) => {
rl.question(
chalk`Please authorize at least one account at the URL above.\n\n` +
chalk`Which account did you authorize for use with NEAR Shell?\n` +
chalk`{bold Enter it here (if not redirected automatically):}\n`, async (accountId) => {
resolve(accountId);
});
});
};
let accountId;
if (!tempUrl) {
accountId = await getAccountFromConsole();
} else {
accountId = await new Promise((resolve, reject) => {
let resolved = false;
const resolveOnce = (result) => { if (!resolved) resolve(result); resolved = true; };
getAccountFromWebpage()
.then(resolveOnce); // NOTE: error ignored on purpose
getAccountFromConsole()
.then(resolveOnce)
.catch(reject);
});
}
rl.close();
capture.cancel();
// verify the accountId if we captured it or ...
try {
await verify(accountId, keyPair, options);
} catch (error) {
console.error('Failed to verify accountId.', error.message);
}
}
};
exports.viewAccount = async function(options) {
let near = await connect(options);
let account = await near.account(options.accountId);
let state = await account.state();
if (state && state.amount) {
state['formattedAmount'] = utils.format.formatNearAmount(state.amount);
}
console.log(`Account ${options.accountId}`);
console.log(inspectResponse(state));
};
exports.deleteAccount = async function(options) {
console.log(
`Deleting account. Account id: ${options.accountId}, node: ${options.nodeUrl}, helper: ${options.helperUrl}, beneficiary: ${options.beneficiaryId}`);
const near = await connect(options);
const account = await near.account(options.accountId);
await account.deleteAccount(options.beneficiaryId);
console.log(`Account ${options.accountId} for network "${options.networkId}" was deleted.`);
};
exports.keys = async function(options) {
let near = await connect(options);
let account = await near.account(options.accountId);
let accessKeys = await account.getAccessKeys();
console.log(`Keys for account ${options.accountId}`);
console.log(inspectResponse(accessKeys));
};
exports.sendMoney = async function(options) {
console.log(`Sending ${options.amount} NEAR to ${options.receiver} from ${options.sender}`);
const near = await connect(options);
const account = await near.account(options.sender);
console.log(inspectResponse(await account.sendMoney(options.receiver, utils.format.parseNearAmount(options.amount))));
};
exports.stake = async function(options) {
console.log(`Staking ${options.amount} (${utils.format.parseNearAmount(options.amount)}) on ${options.accountId} with public key = ${options.stakingKey}.`);
const near = await connect(options);
const account = await near.account(options.accountId);
const result = await account.stake(options.stakingKey, utils.format.parseNearAmount(options.amount));
console.log(inspectResponse(result));
};