@taqueria/plugin-taquito 0.2.1 → 0.4.0-rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/originate.ts CHANGED
@@ -1,201 +1,234 @@
1
- import { SanitizedArgs, PluginResponse, AccountDetails, Failure, LikeAPromise, Config, NetworkConfig, SandboxConfig} from "@taqueria/node-sdk/types";
2
- import glob from 'fast-glob'
3
- import {join} from 'path'
4
- import { TezosToolkit } from '@taquito/taquito';
5
- import {readFile} from 'fs/promises'
6
- import { InMemorySigner, importKey } from '@taquito/signer';
7
- import { sendAsyncJsonRes } from "@taqueria/node-sdk";
8
-
9
- type Opts = SanitizedArgs & Record<string, unknown>
10
-
11
- interface OriginationResult {
12
- contract: string
13
- address: string
14
- destination: string
15
- }
16
-
17
- const getContractAbspath = (contractFilename: string, parsedArgs: Opts) =>
18
- join(parsedArgs.artifactsDir, /\.tz$/.test(contractFilename) ? contractFilename : `${contractFilename}.tz`)
19
-
20
-
21
- const originateContractToSandbox = async (contractFilename: string, parsedArgs: Opts, storage: unknown, sandboxName: string, sandbox: SandboxConfig | undefined): LikeAPromise<OriginationResult, Failure<unknown>> => {
22
- try {
23
- if (sandbox && sandbox.rpcUrl) {
24
- const contractAbspath = getContractAbspath(contractFilename, parsedArgs)
25
- const tezos = new TezosToolkit(sandbox.rpcUrl)
26
- const secretKey = getAccountSecretKey(sandbox)
27
- if (secretKey) {
28
- tezos.setProvider({
29
- signer: new InMemorySigner(secretKey),
30
- });
31
-
32
- const contractData = await readFile(contractAbspath, "utf-8")
33
- return tezos.contract.originate({
34
- code: contractData,
35
- storage: storage
36
- })
37
- .then(operation => ({
38
- contract: contractFilename,
39
- address: operation.contractAddress as string,
40
- destination: sandboxName
41
- }))
42
- .catch(previous => Promise.reject({
43
- errCode: "E_ORIGINATE",
44
- errMsg: `Could not originate ${contractFilename} on the sandbox '${sandboxName}'`,
45
- previous
46
- }))
47
- }
48
- else {
49
- return Promise.reject({
50
- errCode: "E_INVALID_SANDBOX_ACCOUNT",
51
- errMsg: `Please configure a default account for the ${sandboxName} to be used for origination.`,
52
- context: sandbox
53
- })
54
- }
55
- }
56
- return Promise.reject({
57
- errCode: "E_INVALID_SANDBOX_URL",
58
- errMsg: 'The sandbox configuration is invalid and missing the RPC url',
59
- context: sandbox
60
- })
61
- }
62
- catch (err) {
63
- return Promise.reject({
64
- errCode: "E_ORIGINATE",
65
- errMsg: "An unexpected error occured when trying to originate a contract",
66
- previous: err
67
- })
68
- }
69
- }
70
-
71
- const originateContractToNetwork = async (contractFilename: string, parsedArgs: Opts, storage: unknown, networkName: string, network: NetworkConfig|undefined): LikeAPromise<OriginationResult, Failure<unknown>> => {
72
- try {
73
- if (network && network.rpcUrl) {
74
- const contractAbspath = getContractAbspath(contractFilename, parsedArgs)
75
- const tezos = new TezosToolkit(network.rpcUrl)
76
- if (network.faucet) {
77
- await importKey(tezos, network.faucet.email, network.faucet.password, network.faucet.mnemonic.join(' '), network.faucet.activation_code)
78
-
79
- const contractData = await readFile(contractAbspath, "utf-8")
80
- return tezos.contract.originate({
81
- code: contractData,
82
- storage: storage
83
- })
84
- .then(operation => ({
85
- contract: contractFilename,
86
- address: operation.contractAddress as string,
87
- destination: networkName
88
- }))
89
- .catch(previous => Promise.reject({
90
- errCode: "E_ORIGINATE",
91
- errMsg: `Could not originate ${contractFilename} on the network '${networkName}'`,
92
- previous
93
- }))
94
- }
95
- else {
96
- return Promise.reject({
97
- errCode: "E_INVALID_NETWORK_FAUCET",
98
- errMsg: `Please configure a faucet for the ${network} network to be used for origination.`,
99
- context: network
100
- })
101
- }
102
- }
103
- return Promise.reject({
104
- errCode: "E_INVALID_NETWORK_URL",
105
- errMsg: 'The network configuration is invalid and missing the RPC url',
106
- context: network
107
- })
108
- }
109
- catch (err) {
110
- return Promise.reject({
111
- errCode: "E_ORIGINATE",
112
- errMsg: "An unexpected error occured when trying to originate a contract",
113
- previous: err
114
- })
115
- }
116
- }
117
-
118
- const getNetworkConfig = (networkName: string, config: Config) => {
119
- return !config.network[networkName]
120
- ? undefined
121
- : config.network[networkName]
1
+ import {
2
+ getCurrentEnvironmentConfig,
3
+ getDefaultAccount,
4
+ getInitialStorage,
5
+ getNetworkConfig,
6
+ getSandboxAccountConfig,
7
+ getSandboxAccountNames,
8
+ getSandboxConfig,
9
+ sendAsyncErr,
10
+ sendErr,
11
+ sendJsonRes,
12
+ } from '@taqueria/node-sdk';
13
+ import { LikeAPromise, PluginResponse, Protocol, RequestArgs, TaqError } from '@taqueria/node-sdk/types';
14
+ import { OperationContentsAndResultOrigination } from '@taquito/rpc';
15
+ import { importKey, InMemorySigner } from '@taquito/signer';
16
+ import { TezosToolkit, WalletOperationBatch } from '@taquito/taquito';
17
+ import { BatchWalletOperation } from '@taquito/taquito/dist/types/wallet/batch-operation';
18
+ import glob from 'fast-glob';
19
+ import { readFile } from 'fs/promises';
20
+ import { join } from 'path';
21
+
22
+ interface Opts extends RequestArgs.t {
23
+ contract?: string;
122
24
  }
123
25
 
124
- const getSandboxConfig = (sandboxName: string, config: Config) => {
125
- return !config.sandbox[sandboxName]
126
- ? undefined
127
- : config.sandbox[sandboxName]
26
+ interface ContractStorageMapping {
27
+ filename: string;
28
+ storage?: unknown;
128
29
  }
129
30
 
130
- const getAccountSecretKey = (sandbox: SandboxConfig) => {
131
- if (sandbox.accounts && sandbox.accounts.default) {
132
- const accountName = (sandbox.accounts.default as string);
133
- const accountDetails = sandbox.accounts[accountName] as AccountDetails
134
- if (accountDetails.keys) return accountDetails.keys.secretKey.replace(/unencrypted:/, '')
135
- }
136
-
137
- return undefined
138
- }
139
-
140
- const originateContract = (parsedArgs: Opts) => (contractFilename: string) => {
141
- // TODO: Should getting the default environment be provided by the SDK or the framework?
142
- const currentEnv = parsedArgs.env
143
- ? (parsedArgs.env as string)
144
- : (
145
- parsedArgs.config.environment
146
- ? parsedArgs.config.environment.default
147
- : 'development'
148
- )
149
- const env = parsedArgs.config.environment && parsedArgs.config.environment[currentEnv]
150
- ? parsedArgs.config.environment[currentEnv]
151
- : undefined
152
-
153
- if (!env) {
154
- return Promise.reject({
155
- errCode: "E_INVALID_ENV",
156
- errMsg: `No environment configured in your configuration file called ${parsedArgs.env}`,
157
- context: parsedArgs.config
158
- })
159
- }
160
-
161
- if (!env.storage || !env.storage[contractFilename]) {
162
- return Promise.reject({
163
- errCode: "E_INVALID_STORAGE",
164
- errMsg: `No storage configured in your configuration file for ${contractFilename}`,
165
- context: env
166
- })
167
- }
168
-
169
- const networkProcesses = !env.networks ? [] : env.networks.reduce(
170
- (retval: LikeAPromise<OriginationResult, Failure<unknown>>[], network) =>
171
- getNetworkConfig(network, parsedArgs.config)
172
- ? [...retval, originateContractToNetwork(contractFilename, parsedArgs, env.storage[contractFilename], network, getNetworkConfig(network, parsedArgs.config))]
173
- : retval,
174
- []
175
- )
176
-
177
- const allProcesses = !env.sandboxes ? [] : env.sandboxes.reduce(
178
- (retval: LikeAPromise<OriginationResult, Failure<unknown>>[], sandbox) => getSandboxConfig(sandbox, parsedArgs.config)
179
- ? [...retval, originateContractToSandbox(contractFilename, parsedArgs, env.storage[contractFilename], sandbox, getSandboxConfig(sandbox, parsedArgs.config))]
180
- : retval
181
- ,
182
- networkProcesses
183
- )
184
-
185
- return Promise.all(allProcesses)
186
- }
187
-
188
- const originateAll = (parsedArgs: Opts) =>
189
- glob("**/*.tz", {cwd: parsedArgs.artifactsDir})
190
- .then(files => Promise.all(files.map(originateContract(parsedArgs))))
191
- .then(results => results.flat(1))
192
-
193
- export const originate = <T>(parsedArgs: Opts): LikeAPromise<PluginResponse, Failure<T>> => {
194
- const p = parsedArgs.contract
195
- ? originateContract(parsedArgs) (parsedArgs.contract as string)
196
- : originateAll(parsedArgs)
197
-
198
- return p.then(sendAsyncJsonRes)
31
+ interface OriginationResult {
32
+ contract: string;
33
+ address: string;
34
+ destination: string;
199
35
  }
200
36
 
201
- export default originate
37
+ const getFirstAccountAlias = (sandboxName: string, opts: Opts) => {
38
+ const aliases = getSandboxAccountNames(opts)(sandboxName);
39
+ return aliases.shift();
40
+ };
41
+
42
+ const getContractAbspath = (contractFilename: string, parsedArgs: Opts) =>
43
+ join(parsedArgs.config.artifactsDir, /\.tz$/.test(contractFilename) ? contractFilename : `${contractFilename}.tz`);
44
+
45
+ const addOrigination = (parsedArgs: Opts, batch: Promise<WalletOperationBatch>) =>
46
+ async (mapping: ContractStorageMapping) => {
47
+ const contractAbspath = getContractAbspath(mapping.filename, parsedArgs);
48
+ const contractData = await readFile(contractAbspath, 'utf-8');
49
+ return (await batch).withOrigination({
50
+ code: contractData,
51
+ storage: mapping.storage,
52
+ });
53
+ };
54
+
55
+ const getValidContracts = async (parsedArgs: Opts) => {
56
+ const contracts = parsedArgs.contract
57
+ ? [parsedArgs.contract]
58
+ : (await glob('**/*.tz', { cwd: parsedArgs.config.artifactsDir })) as string[];
59
+
60
+ return contracts.reduce(
61
+ (retval, filename) => {
62
+ const storage = getInitialStorage(parsedArgs)(filename);
63
+ if (!storage) throw (`No initial storage provided for ${filename}`);
64
+ return [...retval, { filename, storage }];
65
+ },
66
+ [] as ContractStorageMapping[],
67
+ );
68
+ };
69
+
70
+ const mapOpToContract = async (contracts: ContractStorageMapping[], op: BatchWalletOperation, destination: string) => {
71
+ const results = await op.operationResults();
72
+
73
+ return contracts.reduce(
74
+ (retval, contract) => {
75
+ // If initial storage was provided for the contract
76
+ // then we submitted an operation to originate that contract
77
+ if (contract.storage) {
78
+ // WARNING - using side effect here.
79
+ // For each iteration of reduce, results array is being modified-in-place.
80
+ // TODO: Adjust to use recursion to avoid side-effect.
81
+ const result = results.shift() as OperationContentsAndResultOrigination;
82
+ const address = result && result.metadata.operation_result.originated_contracts
83
+ ? result.metadata.operation_result.originated_contracts.join(',')
84
+ : 'Error';
85
+
86
+ return [
87
+ ...retval,
88
+ {
89
+ contract: contract.filename,
90
+ address,
91
+ destination,
92
+ },
93
+ ];
94
+ }
95
+
96
+ return [
97
+ ...retval,
98
+ {
99
+ contract: contract.filename,
100
+ address: 'Error',
101
+ destination,
102
+ },
103
+ ];
104
+ },
105
+ [] as OriginationResult[],
106
+ );
107
+ };
108
+
109
+ const createBatch = async (parsedArgs: Opts, tezos: TezosToolkit, destination: string) => {
110
+ const contracts = await getValidContracts(parsedArgs);
111
+
112
+ const batch = await contracts.reduce(
113
+ (batch, contractMapping) =>
114
+ contractMapping.storage
115
+ ? addOrigination(parsedArgs, batch)(contractMapping)
116
+ : batch,
117
+ Promise.resolve(tezos.wallet.batch()),
118
+ );
119
+
120
+ try {
121
+ const op = await batch.send();
122
+ const confirmed = await op.confirmation();
123
+ return await mapOpToContract(contracts, op, destination);
124
+ } catch (err) {
125
+ const error = (err as { message: string });
126
+ if (error.message) sendErr(error.message);
127
+ return undefined;
128
+ }
129
+ };
130
+
131
+ const originateToNetworks = (parsedArgs: Opts, currentEnv: Protocol.Environment.t) =>
132
+ currentEnv.networks
133
+ ? currentEnv.networks.reduce(
134
+ (retval, networkName) => {
135
+ const network = getNetworkConfig(parsedArgs)(networkName);
136
+ if (network) {
137
+ if (network.rpcUrl) {
138
+ if (network.faucet) {
139
+ const result = (async () => {
140
+ const tezos = new TezosToolkit(network.rpcUrl as string);
141
+ await importKey(
142
+ tezos,
143
+ network.faucet.email,
144
+ network.faucet.password,
145
+ network.faucet.mnemonic.join(' '),
146
+ network.faucet.activation_code,
147
+ );
148
+ return await createBatch(parsedArgs, tezos, networkName);
149
+ })();
150
+
151
+ return [...retval, result];
152
+ } else sendErr(`Network ${networkName} requires a valid faucet in config.json.`);
153
+ } else sendErr(`Network "${networkName} is missing an RPC url in config.json."`);
154
+ } else {
155
+ sendErr(
156
+ `The current environment is configured to use a network called '${networkName}'; however, no network of this name has been configured in .taq/config.json.`,
157
+ );
158
+ }
159
+
160
+ return retval;
161
+ },
162
+ [] as Promise<OriginationResult[] | undefined>[],
163
+ )
164
+ : [];
165
+
166
+ const originateToSandboxes = (parsedArgs: Opts, currentEnv: Protocol.Environment.t) =>
167
+ currentEnv.sandboxes
168
+ ? currentEnv.sandboxes.reduce(
169
+ (retval, sandboxName) => {
170
+ const sandbox = getSandboxConfig(parsedArgs)(sandboxName);
171
+ if (sandbox) {
172
+ if (sandbox.rpcUrl) {
173
+ let defaultAccount = getDefaultAccount(parsedArgs)(sandboxName);
174
+ if (!defaultAccount) {
175
+ const first = getFirstAccountAlias(sandboxName, parsedArgs);
176
+ if (first) {
177
+ defaultAccount = getSandboxAccountConfig(parsedArgs)(sandboxName)(first);
178
+ sendErr(
179
+ `No default account has been configured for the sandbox called ${sandboxName}. Using the account called ${first} for origination.`,
180
+ );
181
+ }
182
+ }
183
+ if (defaultAccount) {
184
+ const secretKey = defaultAccount.secretKey;
185
+ const result = (async () => {
186
+ const tezos = new TezosToolkit(sandbox.rpcUrl as string);
187
+ tezos.setProvider({
188
+ signer: new InMemorySigner(secretKey.replace(/^unencrypted:/, '')),
189
+ });
190
+ return await createBatch(parsedArgs, tezos, sandboxName);
191
+ })();
192
+
193
+ return [...retval, result];
194
+ } else sendErr(`No accounts are available for the sandbox called ${sandboxName} to perform origination.`);
195
+ } else sendErr(`Sandbox "${sandboxName} is missing an RPC url in config.json."`);
196
+ } else {
197
+ sendErr(
198
+ `The current environment is configured to use a sandbox called '${sandboxName}'; however, no sandbox of this name has been configured in .taq/config.json.`,
199
+ );
200
+ }
201
+
202
+ return retval;
203
+ },
204
+ [] as Promise<OriginationResult[] | undefined>[],
205
+ )
206
+ : [];
207
+
208
+ export const originate = <T>(parsedArgs: Opts): LikeAPromise<PluginResponse, TaqError.t> => {
209
+ const env = getCurrentEnvironmentConfig(parsedArgs);
210
+
211
+ if (!env) {
212
+ return sendAsyncErr(`There is no environment called ${parsedArgs.env} in your config.json.`);
213
+ }
214
+
215
+ const jobs = [
216
+ ...originateToNetworks(parsedArgs, env),
217
+ ...originateToSandboxes(parsedArgs, env),
218
+ ];
219
+
220
+ return Promise.all(jobs)
221
+ .then(jobs =>
222
+ jobs.reduce(
223
+ (retval, originations) => {
224
+ return originations
225
+ ? [...retval as OriginationResult[], ...originations]
226
+ : retval;
227
+ },
228
+ [],
229
+ )
230
+ )
231
+ .then(results => results && results.length > 0 ? sendJsonRes(results) : sendErr(`No contracts originated.`));
232
+ };
233
+
234
+ export default originate;
package/package.json CHANGED
@@ -1,54 +1,54 @@
1
1
  {
2
- "name": "@taqueria/plugin-taquito",
3
- "version": "0.2.1",
4
- "description": "A taqueria plugin for originating smart contracts using Taquito",
5
- "targets": {
6
- "default": {
7
- "source": "./index.ts",
8
- "distDir": "./",
9
- "context": "node",
10
- "isLibrary": true
11
- }
12
- },
13
- "scripts": {
14
- "test": "echo \"Error: no test specified\" && exit 1",
15
- "pluginInfo": "npx ts-node index.ts --taqRun pluginInfo --i18n {\"foo:\"\"bar\"}",
16
- "build": "npx parcel build --no-cache 2>&1",
17
- "debugPluginInfo": "node --inspect-brk index.js --taqRun pluginInfo --i18n {\"foo:\"\"bar\"}"
18
- },
19
- "keywords": [
20
- "taqueria",
21
- "tezos",
22
- "originate",
23
- "deploy",
24
- "ecad",
25
- "ecadlabs",
26
- "plugin",
27
- "taquito",
28
- "smart contract"
29
- ],
30
- "engines": {
31
- "node": ">=16"
32
- },
33
- "author": "ECAD Labs",
34
- "license": "Apache-2.0",
35
- "repository": {
36
- "type": "git",
37
- "url": "https://github.com/ecadlabs/taqueria.git",
38
- "directory": "taqueria-plugin-taquito"
39
- },
40
- "bugs": {
41
- "url": "https://github.com/ecadlabs/taqueria/issues"
42
- },
43
- "homepage": "https://github.com/ecadlabs/taqueria#readme",
44
- "devDependencies": {
45
- "parcel": "^2.0.1",
46
- "typescript": "4.5.4"
47
- },
48
- "dependencies": {
49
- "@taquito/signer": "^11.1.0",
50
- "@taquito/taquito": "^11.0.2",
51
- "fast-glob": "^3.2.10",
52
- "@taqueria/node-sdk": "^0.2.1"
53
- }
2
+ "name": "@taqueria/plugin-taquito",
3
+ "version": "0.4.0-rc1",
4
+ "description": "A taqueria plugin for originating smart contracts using Taquito",
5
+ "targets": {
6
+ "default": {
7
+ "source": "./index.ts",
8
+ "distDir": "./",
9
+ "context": "node",
10
+ "isLibrary": true
11
+ }
12
+ },
13
+ "scripts": {
14
+ "test": "echo \"Error: no test specified\" && exit 1",
15
+ "pluginInfo": "npx ts-node index.ts --taqRun pluginInfo --i18n {\"foo:\"\"bar\"}",
16
+ "build": "npx tsc -noEmit && npx parcel build --no-cache 2>&1",
17
+ "debugPluginInfo": "node --inspect-brk index.js --taqRun pluginInfo --i18n {\"foo:\"\"bar\"}"
18
+ },
19
+ "keywords": [
20
+ "taqueria",
21
+ "tezos",
22
+ "originate",
23
+ "deploy",
24
+ "ecad",
25
+ "ecadlabs",
26
+ "plugin",
27
+ "taquito",
28
+ "smart contract"
29
+ ],
30
+ "engines": {
31
+ "node": ">=16"
32
+ },
33
+ "author": "ECAD Labs",
34
+ "license": "Apache-2.0",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "https://github.com/ecadlabs/taqueria.git",
38
+ "directory": "taqueria-plugin-taquito"
39
+ },
40
+ "bugs": {
41
+ "url": "https://github.com/ecadlabs/taqueria/issues"
42
+ },
43
+ "homepage": "https://github.com/ecadlabs/taqueria#readme",
44
+ "devDependencies": {
45
+ "parcel": "^2.6.0",
46
+ "typescript": "^4.7.2"
47
+ },
48
+ "dependencies": {
49
+ "@taqueria/node-sdk": "^0.4.0",
50
+ "@taquito/signer": "^12.1.1",
51
+ "@taquito/taquito": "^12.1.1",
52
+ "fast-glob": "^3.2.11"
53
+ }
54
54
  }