From 7b9dfba6458ddbd9863d60fa65bf9b15194279d0 Mon Sep 17 00:00:00 2001 From: Claudiu Teodor Filip Date: Tue, 10 Sep 2019 19:36:01 +0300 Subject: [PATCH 1/8] refactor: added functional options support to most public methods of Contract and Wavelet classes --- src/main.js | 164 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 132 insertions(+), 32 deletions(-) diff --git a/src/main.js b/src/main.js index 3f2fd1f..80a3b40 100644 --- a/src/main.js +++ b/src/main.js @@ -220,15 +220,47 @@ class PayloadBuilder { } class Contract { + + static setAmount(value) { + return config => { + config.amount = BigInt(value); + }; + } + + static setRecipient(value) { + return config => { + config.recipient = value; + } + } + + static setGasLimit(value) { + return config => { + config.gas_limit = BigInt(value); + }; + } + + static setGasDeposit(value) { + return config => { + config.gas_deposit = BigInt(value); + }; + } + static setParams(value) { + return config => { + config.params = value; + }; + } /** * A Wavelet smart contract execution simulator. * * @param {Wavelet} client Client instance which is connected to a single Wavelet node. * @param {string} contract_id Hex-encoded ID of a smart contract. */ - constructor(client, contract_id) { + constructor(client, ...opts) { this.client = client; - this.contract_id = contract_id; + opts.forEach(opt => { + opt(this); + }); + // this.contract_id = contract_id; this.contract_payload = { round_idx: BigInt(0), @@ -296,7 +328,18 @@ class Contract { * @param {...{type: ('int16'|'int32'|'int64'|'uint16'|'uint32'|'uint64'|'byte'|'raw'|'bytes'|'string'), value: number|string|ArrayBuffer|Uint8Array}} func_params Variadic list of arguments. * @returns {{result: string|undefined, logs: Array}} */ - test(wallet, func_name, amount_to_send, ...func_params) { + test(wallet, func_name, ...opts) { + + const config = { + gas_deposit: JSBI.BigInt(0), + gas_limit: JSBI.BigInt(0), + amount: JSBI.BigInt(0), + params: [] + }; + opts.forEach(opt => { + opt(config); + }); + if (this.vm === undefined) throw new Error("init() needs to be called before calling test()"); func_name = "_contract_" + func_name; @@ -305,8 +348,8 @@ class Contract { throw new Error("could not find function in smart contract"); } - this.contract_payload.params = this.parseFunctionParams(...func_params); - this.contract_payload.amount = amount_to_send; + this.contract_payload.params = this.parseFunctionParams(...config.params); + this.contract_payload.amount = config.amount; this.contract_payload.sender_id = Buffer.from(wallet.publicKey).toString("hex"); this.rebuildContractPayload(); @@ -317,7 +360,7 @@ class Contract { this.vm.instance.exports[func_name](); // Collect simulated execution results. - const res = {result: this.result, logs: this.logs}; + const res = { result: this.result, logs: this.logs }; // Reset the browser VM. new Uint8Array(this.vm.instance.exports.memory.buffer, 0, copy.byteLength).set(copy); @@ -343,8 +386,21 @@ class Contract { * @param {...{type: ('int16'|'int32'|'int64'|'uint16'|'uint32'|'uint64'|'byte'|'raw'|'bytes'|'string'), value: number|string|ArrayBuffer|Uint8Array}} func_params Variadic list of arguments. * @returns {Promise} Response from the Wavelet node. */ - async call(wallet, func_name, amount_to_send, gas_limit, gas_deposit, ...func_params) { - return await this.client.transfer(wallet, this.contract_id, amount_to_send, gas_limit, gas_deposit, func_name, this.parseFunctionParams(...func_params)); + async call(wallet, func_name, ...opts) { + // amount_to_send, gas_limit, gas_deposit, ...func_params + const config = { + func_name, + recipient: this.contract_id, + wallet, + gas_deposit: JSBI.BigInt(0), + gas_limit: JSBI.BigInt(0), + amount: JSBI.BigInt(0), + params: [] + }; + opts.forEach(opt => opt(config)); + config.params = this.parseFunctionParams(...config.params); + + return await this.client._send(config); } /** @@ -498,10 +554,16 @@ class Wavelet { * @param {string} host Address to the HTTP API of a Wavelet node. * @param {Object=} opts Default options to be passed for making any HTTP request calls using this client instance (optional). */ - constructor(host, opts = {}) { + constructor(host, ...opts) { this.host = host; + + opts.forEach(opt => { + opt(this); + }); + this.opts = { - ...opts, transformRequest: [(data, headers) => { + ...this.opts, + transformRequest: [(data, headers) => { headers.common = {}; return data @@ -516,7 +578,7 @@ class Wavelet { * @returns {Promise} */ async getNodeInfo(opts) { - return (await axios.get(`${this.host}/ledger`, {...this.opts, ...opts})).data; + return (await axios.get(`${this.host}/ledger`, { ...this.opts, ...opts })).data; } /** @@ -527,7 +589,7 @@ class Wavelet { * @returns {Promise} */ async getTransaction(id, opts = {}) { - return (await axios.get(`${this.host}/tx/${id}`, {...this.opts, ...opts})).data; + return (await axios.get(`${this.host}/tx/${id}`, { ...this.opts, ...opts })).data; } /** @@ -538,7 +600,7 @@ class Wavelet { * @returns {Promise<{public_key: string, nonce: bigint, balance: bigint, stake: bigint, reward: bigint, is_contract: boolean, num_mem_pages: bigint}>} */ async getAccount(id, opts = {}) { - return (await axios.get(`${this.host}/accounts/${id}`, {...this.opts, ...opts})).data; + return (await axios.get(`${this.host}/accounts/${id}`, { ...this.opts, ...opts })).data; } /** @@ -608,9 +670,32 @@ class Wavelet { * @param {Object=} opts Options to be passed on for making the specified HTTP request call (optional). * @returns {Promise} */ - async transfer(wallet, recipient, amount, gas_limit = 0, gas_deposit = 0, func_name = "", func_payload = new Uint8Array(new ArrayBuffer(0)), opts = {}) { + async transfer(wallet, recipient, ...opts) { + + const config = { + recipient, + wallet + }; + opts.forEach(opt => opt(config)); + return this._send(config); + } + + async _send(config) { const builder = new PayloadBuilder(); + const { + recipient, + amount, + + gas_deposit = 0, + gas_limit = 0, + func_payload = new Uint8Array(new ArrayBuffer(0)), + wallet, + ...opts + } = config; + + let { func_name = "" } = config; + builder.writeBytes(Buffer.from(recipient, "hex")); builder.writeUint64(amount); @@ -643,13 +728,16 @@ class Wavelet { * @param {Object=} opts Options to be passed on for making the specified HTTP request call (optional). * @returns {Promise<*>} */ - async placeStake(wallet, amount, opts = {}) { + async placeStake(wallet, amount, ...opts) { + const config = {}; + opts.forEach(opt => opt(config)); + const builder = new PayloadBuilder(); builder.writeByte(1); builder.writeUint64(amount); - return await this.sendTransaction(wallet, TAG_STAKE, builder.getBytes(), opts); + return await this.sendTransaction(wallet, TAG_STAKE, builder.getBytes(), config); } /** @@ -660,13 +748,16 @@ class Wavelet { * @param {Object=} opts Options to be passed on for making the specified HTTP request call (optional). * @returns {Promise<*>} */ - async withdrawStake(wallet, amount, opts = {}) { + async withdrawStake(wallet, amount, ...opts) { + const config = {}; + opts.forEach(opt => opt(config)); + const builder = new PayloadBuilder(); builder.writeByte(0); builder.writeUint64(amount); - return await this.sendTransaction(wallet, TAG_STAKE, builder.getBytes(), opts); + return await this.sendTransaction(wallet, TAG_STAKE, builder.getBytes(), config); } /** @@ -678,13 +769,16 @@ class Wavelet { * @param {Object=} opts Options to be passed on for making the specified HTTP request call (optional). * @returns {Promise<*>} */ - async withdrawReward(wallet, amount, opts = {}) { + async withdrawReward(wallet, amount, ...opts) { + const config = {}; + opts.forEach(opt => opt(config)); + const builder = new PayloadBuilder(); builder.writeByte(2); builder.writeUint64(amount); - return await this.sendTransaction(wallet, TAG_STAKE, builder.getBytes(), opts); + return await this.sendTransaction(wallet, TAG_STAKE, builder.getBytes(), config); } /** @@ -735,9 +829,9 @@ class Wavelet { const signature = Buffer.from(nacl.sign.detached(builder.getBytes(), wallet.secretKey)).toString("hex"); const sender = Buffer.from(wallet.publicKey).toString("hex"); - const req = {sender, tag, payload: payload_hex, signature}; + const req = { sender, tag, payload: payload_hex, signature }; - return (await axios.post(`${this.host}/tx/send`, JSON.stringify(req), {...this.opts, ...opts})).data; + return (await axios.post(`${this.host}/tx/send`, JSON.stringify(req), { ...this.opts, ...opts })).data; } /** @@ -747,9 +841,12 @@ class Wavelet { * @param {{id: string|undefined}} opts * @returns {Promise} Websocket client. */ - async pollAccounts(callbacks = {}, opts = {}) { + async pollAccounts(callbacks = {}, ...opts) { + const config = {}; + opts.forEach(opt => opt(config)); + let params = {}; - if (opts && opts.id && typeof opts.id === "string" && opts.id.length === 64) params.id = opts.id; + if (config && config.id && typeof config.id === "string" && config.id.length === 64) params.id = config.id; return await this.pollWebsocket('/poll/accounts', params, data => { if (callbacks && callbacks.onAccountUpdated) { @@ -769,12 +866,15 @@ class Wavelet { * @param {{id: string|undefined, tag: number|undefined, sender: string|undefined, creator: string|undefined}} opts * @returns {Promise} Websocket client. */ - async pollTransactions(callbacks = {}, opts = {}) { + async pollTransactions(callbacks = {}, ...opts) { + const config = {}; + opts.forEach(opt => opt(config)); + let params = {}; - if (opts && opts.id && typeof opts.id === "string" && opts.id.length === 64) params.id = opts.id; - if (opts && opts.tag && typeof opts.tag === "number") params.tag = opts.tag; - if (opts && opts.sender && typeof opts.sender === "string" && opts.sender.length === 64) params.sender = opts.sender; - if (opts && opts.creator && typeof opts.creator === "string" && opts.creator.length === 64) params.creator = opts.creator; + if (config && config.id && typeof config.id === "string" && config.id.length === 64) params.id = config.id; + if (config && config.tag && typeof config.tag === "number") params.tag = config.tag; + if (config && config.sender && typeof config.sender === "string" && config.sender.length === 64) params.sender = config.sender; + if (config && config.creator && typeof config.creator === "string" && config.creator.length === 64) params.creator = config.creator; return await this.pollWebsocket('/poll/tx', params, data => { if (!Array.isArray(data)) { @@ -895,7 +995,7 @@ class Wavelet { const recipient = Buffer.from(new Uint8Array(buf, 0, 32)).toString('hex'); const amount = view.getBigUint64(32, true); - let tx = {recipient, amount}; + let tx = { recipient, amount }; if (buf.byteLength > 32 + 8) { tx.gasLimit = view.getBigUint64(32 + 8, true); @@ -947,7 +1047,7 @@ class Wavelet { const amount = view.getBigUint64(1, true); - let tx = {amount}; + let tx = { amount }; switch (opcode) { case 0: @@ -992,4 +1092,4 @@ class Wavelet { } } -export default {Wavelet, Contract, TAG_NOP, TAG_TRANSFER, TAG_CONTRACT, TAG_STAKE, TAG_BATCH}; +export default { Wavelet, Contract, TAG_NOP, TAG_TRANSFER, TAG_CONTRACT, TAG_STAKE, TAG_BATCH }; From b412f3f1c94e24fe69466fc0804711325c6f60c1 Mon Sep 17 00:00:00 2001 From: Claudiu Teodor Filip Date: Wed, 11 Sep 2019 10:40:41 +0300 Subject: [PATCH 2/8] refactor: added more functional options support and a custom SetOption to set any option by key --- src/main.js | 277 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 221 insertions(+), 56 deletions(-) diff --git a/src/main.js b/src/main.js index 80a3b40..7333cde 100644 --- a/src/main.js +++ b/src/main.js @@ -218,37 +218,117 @@ class PayloadBuilder { return new Uint8Array(this.buf.slice(0, this.offset)); } } + /** + * Sets value for custom option key + * + * @param {bigint} round_idx Consensus round index. + */ +const SetOption = (key, value) => { + return config => { + config[key] = value; + }; +}; class Contract { - static setAmount(value) { + static Amount(value) { return config => { config.amount = BigInt(value); }; } - static setRecipient(value) { + static Recipient(value) { return config => { config.recipient = value; } } - static setGasLimit(value) { + static ContractId(value) { + return config => { + config.contract_id = value; + } + } + + static GasLimit(value) { return config => { config.gas_limit = BigInt(value); }; } - static setGasDeposit(value) { + static GasDeposit(value) { return config => { config.gas_deposit = BigInt(value); }; } - static setParams(value) { + + static Params(value) { return config => { config.params = value; }; } + + static Int16(value) { + return { + type: 'int16', + value + } + } + static Int32(value) { + return { + type: 'int32', + value + } + } + static Int64(value) { + return { + type: 'int64', + value: BigInt(value) + } + } + static Uint16(value) { + return { + type: 'uint16', + value + } + } + static Uint32(value) { + return { + type: 'uint32', + value + } + } + static Uint64(value) { + return { + type: 'uint64', + value + } + } + static Byte(value) { + return { + type: 'byte', + value + } + } + + static bytes(value) { + return { + type: 'bytes', + value + } + } + static string(value) { + return { + type: 'string', + value + } + } + + static Raw(value) { + return { + type: 'raw', + value + }; + } /** * A Wavelet smart contract execution simulator. * @@ -334,7 +414,8 @@ class Contract { gas_deposit: JSBI.BigInt(0), gas_limit: JSBI.BigInt(0), amount: JSBI.BigInt(0), - params: [] + params: [], + sender_id: Buffer.from(wallet.publicKey).toString("hex") }; opts.forEach(opt => { opt(config); @@ -350,7 +431,7 @@ class Contract { this.contract_payload.params = this.parseFunctionParams(...config.params); this.contract_payload.amount = config.amount; - this.contract_payload.sender_id = Buffer.from(wallet.publicKey).toString("hex"); + this.contract_payload.sender_id = config.sender_id; this.rebuildContractPayload(); // Clone the current browser VM's memory. @@ -554,6 +635,59 @@ class Wavelet { * @param {string} host Address to the HTTP API of a Wavelet node. * @param {Object=} opts Default options to be passed for making any HTTP request calls using this client instance (optional). */ + + static Creator(value) { + return config => { + config.creator = value; + }; + } + static Sender(value) { + return config => { + config.sender = value; + }; + } + static Tag(value) { + return config => { + config.tag = value; + }; + } + static Id(value) { + return config => { + config.id = value; + }; + } + static TransactionApplied(fn) { + return config => { + config.onTransactionApplied = fn; + }; + } + static TransactionRejected(fn) { + return config => { + config.onTransactionRejected = fn; + }; + } + static RoundEnded(fn) { + return config => { + config.onRoundEnded = fn; + }; + } + static RoundPruned(fn) { + return config => { + config.onRoundPruned = fn; + }; + } + + static Payload(value) { + return config => { + config.payload = value; + }; + } + static AccountUpdated(fn) { + return config => { + config.onAccountUpdated = fn; + }; + } + constructor(host, ...opts) { this.host = host; @@ -588,8 +722,11 @@ class Wavelet { * @param {Object=} opts Options to be passed on for making the specified HTTP request call (optional). * @returns {Promise} */ - async getTransaction(id, opts = {}) { - return (await axios.get(`${this.host}/tx/${id}`, { ...this.opts, ...opts })).data; + async getTransaction(id, ...opts) { + const config = {}; + opts.forEach(opt => opt(config)); + + return (await axios.get(`${this.host}/tx/${id}`, { ...this.opts, ...config })).data; } /** @@ -599,8 +736,11 @@ class Wavelet { * @param {Object=} opts Options to be passed on for making the specified HTTP request call (optional). * @returns {Promise<{public_key: string, nonce: bigint, balance: bigint, stake: bigint, reward: bigint, is_contract: boolean, num_mem_pages: bigint}>} */ - async getAccount(id, opts = {}) { - return (await axios.get(`${this.host}/accounts/${id}`, { ...this.opts, ...opts })).data; + async getAccount(id, ...opts) { + const config = {}; + opts.forEach(opt => opt(config)); + + return (await axios.get(`${this.host}/accounts/${id}`, { ...this.opts, ...config })).data; } /** @@ -610,7 +750,10 @@ class Wavelet { * @param {Object=} opts Options to be passed on for making the specified HTTP request call (optional). * @returns {Promise} */ - async getCode(id, opts = {}) { + async getCode(id, ...opts) { + const config = {}; + opts.forEach(opt => opt(config)); + return new Uint8Array((await axios.get(`${this.host}/contract/${id}`, { ...this.opts, ...opts, responseType: 'arraybuffer', @@ -627,7 +770,10 @@ class Wavelet { * @returns {Promise} The memory of the given smart contract, which may be used to * initialize a WebAssembly VM with (either on browser/desktop). */ - async getMemoryPages(id, num_mem_pages, opts = {}) { + async getMemoryPages(id, num_mem_pages, ...opts) { + const config = {}; + opts.forEach(opt => opt(config)); + if (num_mem_pages === 0) throw new Error("num pages cannot be zero"); const memory = new Uint8Array(new ArrayBuffer(65536 * num_mem_pages)); @@ -637,7 +783,7 @@ class Wavelet { reqs.push((async () => { try { const res = await axios.get(`${this.host}/contract/${id}/page/${idx}`, { - ...this.opts, ...opts, + ...this.opts, ...config, responseType: 'arraybuffer', responseEncoding: 'binary' }); @@ -786,25 +932,36 @@ class Wavelet { * * @param {nacl.SignKeyPair} wallet Wavelet wallet. * @param {Uint8Array} code Binary of your smart contracts WebAssembly code. - * @param {bigint} gas_limit Gas limit to expend for creating your smart contract, and invoking its init() function. - * @param {bigint=} gas_deposit Amount of gas fees to deposit into a smart contract. - * @param {Object=} params Parameters to be used for invoking your smart contracts init() function. - * @param {Object=} opts Options to be passed on for making the specified HTTP request call (optional). + ** gas_limit - Gas limit to expend for creating your smart contract, and invoking its init() function. + ** gas_deposit - Amount of gas fees to deposit into a smart contract. + ** params - Parameters to be used for invoking your smart contracts init() function. + * @param {{gas_limit: bigint, gas_deposit: bigint=, params:Object= }} opts * @returns {Promise<*>} */ - async deployContract(wallet, code, gas_limit, gas_deposit = 0, params = [], opts = {}) { + async deployContract(wallet, code, ...opts) { + + const config = { + func_name, + recipient: this.contract_id, + wallet, + gas_deposit: JSBI.BigInt(0), + gas_limit: JSBI.BigInt(0), + params: [] + }; + opts.forEach(opt => opt(config)); + + config.params = this.parseFunctionParams(...config.params); code = new Uint8Array(code); - params = new Uint8Array(params); const builder = new PayloadBuilder(); - builder.writeUint64(gas_limit); - builder.writeUint64(gas_deposit); - builder.writeUint32(params.byteLength); - builder.writeBytes(params); + builder.writeUint64(config.gas_limit); + builder.writeUint64(config.gas_deposit); + builder.writeUint32(config.params.byteLength); + builder.writeBytes(config.params); builder.writeBytes(code); - return await this.sendTransaction(wallet, TAG_CONTRACT, builder.getBytes(), opts); + return await this.sendTransaction(wallet, TAG_CONTRACT, builder.getBytes(), config); } /** @@ -837,23 +994,23 @@ class Wavelet { /** * Poll for updates to accounts. * - * @param callbacks - * @param {{id: string|undefined}} opts + * @param {{id: string|undefined, onAccountUpdated: Function}} opts * @returns {Promise} Websocket client. */ - async pollAccounts(callbacks = {}, ...opts) { - const config = {}; + async pollAccounts(...opts) { + const config = { + params: {} + }; opts.forEach(opt => opt(config)); - let params = {}; - if (config && config.id && typeof config.id === "string" && config.id.length === 64) params.id = config.id; + if (config && config.id && typeof config.id === "string" && config.id.length === 64) config.params.id = config.id; - return await this.pollWebsocket('/poll/accounts', params, data => { - if (callbacks && callbacks.onAccountUpdated) { + return await this.pollWebsocket('/poll/accounts', config.params, data => { + if (config.onAccountUpdated) { if (!Array.isArray(data)) { data = [data]; } - data.forEach(item => callbacks.onAccountUpdated(item)); + data.forEach(item => config.onAccountUpdated(item)); } }) } @@ -862,34 +1019,34 @@ class Wavelet { * Poll for updates to either all transactions in the ledger, or transactions made by a certain sender, or * transactions made by a certain creator, or transactions with a specific tag, or just a single transaction. * - * @param callbacks - * @param {{id: string|undefined, tag: number|undefined, sender: string|undefined, creator: string|undefined}} opts + * @param {{id: string|undefined, onTransactionApplied:, onTransactionRejected: Function, tag: number|undefined, sender: string|undefined, creator: string|undefined}} opts * @returns {Promise} Websocket client. */ - async pollTransactions(callbacks = {}, ...opts) { - const config = {}; + async pollTransactions(...opts) { + const config = { + params: {} + }; opts.forEach(opt => opt(config)); - let params = {}; - if (config && config.id && typeof config.id === "string" && config.id.length === 64) params.id = config.id; - if (config && config.tag && typeof config.tag === "number") params.tag = config.tag; - if (config && config.sender && typeof config.sender === "string" && config.sender.length === 64) params.sender = config.sender; - if (config && config.creator && typeof config.creator === "string" && config.creator.length === 64) params.creator = config.creator; + if (config && config.id && typeof config.id === "string" && config.id.length === 64) config.params.id = config.id; + if (config && config.tag && typeof config.tag === "number") config.params.tag = config.tag; + if (config && config.sender && typeof config.sender === "string" && config.sender.length === 64) config.params.sender = config.sender; + if (config && config.creator && typeof config.creator === "string" && config.creator.length === 64) config.params.creator = config.creator; - return await this.pollWebsocket('/poll/tx', params, data => { + return await this.pollWebsocket('/poll/tx', config.params, data => { if (!Array.isArray(data)) { data = [data]; } data.forEach(item => { switch (item.event) { case "rejected": - if (callbacks && callbacks.onTransactionRejected) { - callbacks.onTransactionRejected(item); + if (config.onTransactionRejected) { + config.onTransactionRejected(item); } break; case "applied": - if (callbacks && callbacks.onTransactionApplied) { - callbacks.onTransactionApplied(item); + if (config.onTransactionApplied) { + config.onTransactionApplied(item); } break; } @@ -900,20 +1057,22 @@ class Wavelet { /** * Poll for finality of consensus rounds, or the pruning of consensus rounds. * - * @param callbacks + * @param {{onRoundEnded: Function, onRoundPruned: Function}} opts * @returns {Promise} Websocket client. */ - async pollConsensus(callbacks = {}) { + async pollConsensus(...opts) { + const config = {}; + opts.forEach(opt => opt(config)); return await this.pollWebsocket('/poll/consensus', {}, data => { switch (data.event) { case "round_end": - if (callbacks && callbacks.onRoundEnded) { - callbacks.onRoundEnded(data); + if (config.onRoundEnded) { + config.onRoundEnded(data); } break; case "prune": - if (callbacks && callbacks.onRoundPruned) { - callbacks.onRoundPruned(data); + if (config.onRoundPruned) { + config.onRoundPruned(data); } break; } @@ -978,7 +1137,13 @@ class Wavelet { * @param {string} payload Binary-serialized payload of a transaction. * @returns {{amount: bigint, recipient: string}|{}|Array|{amount: bigint}} Decoded payload of a transaction. */ - static parseTransaction(tag, payload) { + static parseTransaction(...opts) { + const config = { + payload: "" + }; + opts.forEach(opt => opt(config)); + const { tag, payload } = config; + switch (tag) { case TAG_NOP: { return {} @@ -1092,4 +1257,4 @@ class Wavelet { } } -export default { Wavelet, Contract, TAG_NOP, TAG_TRANSFER, TAG_CONTRACT, TAG_STAKE, TAG_BATCH }; +export default { Wavelet, Contract, TAG_NOP, TAG_TRANSFER, TAG_CONTRACT, TAG_STAKE, TAG_BATCH, SetOption }; From 7d967741d848a370300b41ce6ae14ef788d917a3 Mon Sep 17 00:00:00 2001 From: Claudiu Teodor Filip Date: Wed, 11 Sep 2019 10:44:31 +0300 Subject: [PATCH 3/8] updated readme file with new example --- README.md | 76 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 86df18e..34bc092 100644 --- a/README.md +++ b/README.md @@ -21,53 +21,75 @@ yarn add wavelet-client ## Usage ```javascript -const {Wavelet, Contract, TAG_TRANSFER} = require('..'); +const { Wavelet, Contract, TAG_TRANSFER, SetOption } = require('wavelet-client'); const JSBI = require('jsbi'); const BigInt = JSBI.BigInt; -const client = new Wavelet("http://127.0.0.1:9000"); +const client = new Wavelet('https://testnet.perlin.net'); (async () => { console.log(await client.getNodeInfo()); console.log(await client.getAccount('400056ee68a7cc2695222df05ea76875bc27ec6e61e8e62317c336157019c405')); - const transfer = await client.getTransaction('805e4ff2a9955b804e32579166c8a54e07e3f1c161702254d8778e4805ea12fc'); - console.log(Wavelet.parseTransaction(transfer.tag, transfer.payload)); + try { + const transfer = await client.getTransaction('9eba6ea46d551c60af17837a29a472680043fdf6c9b5de16beb33b3b1b569660'); + console.log(Wavelet.parseTransaction(Wavelet.Tag(transfer.tag), Wavelet.payload(transfer.payload))); - const call = await client.getTransaction('9a8746b7bf7a84af7fbd41520a841e96907bee71a88560af7e6996cfb7682891'); - console.log(Wavelet.parseTransaction(call.tag, call.payload)); + const call = await client.getTransaction('42ec15463eb14d93a63960ade358d15554cb3c6d733670a7e69b96c6f3ec69b4'); + console.log(Wavelet.parseTransaction(Wavelet.Tag(call.tag), Wavelet.payload(transfer.payload))); - const stake = await client.getTransaction('673ef140f8a47980d8684a47bf639624d7a4d8470ad30c1a66a4f417f69ab84a'); - console.log(Wavelet.parseTransaction(stake.tag, stake.payload)); + const stake = await client.getTransaction('5fe8bac3b084c568bf49397333034dcc1d6818756da470fcb3675b95eee68bcd'); + console.log(Wavelet.parseTransaction(Wavelet.Tag(stake.tag), Wavelet.payload(transfer.payload))); + + } catch (err) { + console.error(err); + } const wallet = Wavelet.loadWalletFromPrivateKey('87a6813c3b4cf534b6ae82db9b1409fa7dbd5c13dba5858970b56084c4a930eb400056ee68a7cc2695222df05ea76875bc27ec6e61e8e62317c336157019c405'); - const account = await client.getAccount(Buffer.from(wallet.publicKey).toString("hex")); + const account = await client.getAccount(Buffer.from(wallet.publicKey).toString('hex')); - const contract = new Contract(client, '52bb52e0440ce0aa7a7d2018f5bac21d6abde64f5b9498615ce2bef332bd487a'); + console.log(account); + + const contract = new Contract(client, Contract.ContractId('61820bc6796380c12347f69be171868b4e268204caa76ab68087cbde4f925beb')); await contract.init(); - console.log(contract.test(wallet, 'balance', BigInt(0), - { - type: 'raw', - value: '400056ee68a7cc2695222df05ea76875bc27ec6e61e8e62317c336157019c405' - }, - )); + console.log(contract); + + const params = [ + Contract.Raw('400056ee68a7cc2695222df05ea76875bc27ec6e61e8e62317c336157019c405') + ]; + + const gasLimit = JSBI.subtract(BigInt(account.balance), BigInt(1000000)); + const testResult = contract.test( + wallet, + 'balance', + SetOption('amount', BigInt(0)), + Contract.Params(params) + ); + + console.log(testResult); + + const callResult = await contract.call( + wallet, + 'balance', + Contract.Amount(0), + Contract.GasLimit(gasLimit), + Contract.GasDeposit(0), + Contract.Params(params) + ); - console.log(await contract.call(wallet, 'balance', BigInt(0), BigInt(0), JSBI.subtract(BigInt(account.balance), BigInt(1000000)), - { - type: 'raw', - value: '400056ee68a7cc2695222df05ea76875bc27ec6e61e8e62317c336157019c405' - }, - )); + console.log(callResult); - const consensusPoll = await client.pollConsensus({onRoundEnded: console.log}); - const transactionsPoll = await client.pollTransactions({onTransactionApplied: console.log}, {tag: TAG_TRANSFER, creator: "400056ee68a7cc2695222df05ea76875bc27ec6e61e8e62317c336157019c405"}); - const accountsPoll = await client.pollAccounts({onAccountUpdated: console.log}, {id: "400056ee68a7cc2695222df05ea76875bc27ec6e61e8e62317c336157019c405"}); + const consensusPoll = await client.pollConsensus(Wavelet.RoundEnded(console.log)); + const transactionsPoll = await client.pollTransactions(Wavelet.TransactionApplied(console.log), Wavelet.Tag(TAG_TRANSFER), Wavelet.Creator('400056ee68a7cc2695222df05ea76875bc27ec6e61e8e62317c336157019c405')); + const accountsPoll = await client.pollAccounts(Wavelet.AccountUpdated(console.log), Wavelet.Id('400056ee68a7cc2695222df05ea76875bc27ec6e61e8e62317c336157019c405')); for (let i = 0; i < 100; i++) { - await client.transfer(wallet, 'e49e8be205a00edb45de8183a4374e362efc9a4da56dd7ba17e2dd780501e49f', BigInt(1000000)); + await client.transfer(wallet, + 'e49e8be205a00edb45de8183a4374e362efc9a4da56dd7ba17e2dd780501e49f', + Contract.Amount(1000) + ); } })(); -``` \ No newline at end of file From 91a69b3d0ebbf70d31dd6815252818e581c038f5 Mon Sep 17 00:00:00 2001 From: Claudiu Teodor Filip Date: Wed, 11 Sep 2019 11:12:00 +0300 Subject: [PATCH 4/8] refactor: moved http request options under http key so that unintended option don't get passed to axios --- src/main.js | 175 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 104 insertions(+), 71 deletions(-) diff --git a/src/main.js b/src/main.js index 7333cde..018cdb2 100644 --- a/src/main.js +++ b/src/main.js @@ -218,11 +218,11 @@ class PayloadBuilder { return new Uint8Array(this.buf.slice(0, this.offset)); } } - /** - * Sets value for custom option key - * - * @param {bigint} round_idx Consensus round index. - */ +/** +* Sets value for custom option key +* +* @param {bigint} round_idx Consensus round index. +*/ const SetOption = (key, value) => { return config => { config[key] = value; @@ -629,13 +629,16 @@ class Contract { } class Wavelet { - /** - * A client for interacting with the HTTP API of a Wavelet node. - * - * @param {string} host Address to the HTTP API of a Wavelet node. - * @param {Object=} opts Default options to be passed for making any HTTP request calls using this client instance (optional). - */ - + static Http(value) { + return config => { + config.http = value; + }; + } + static Amount(value) { + return config => { + config.amount = BigInt(value); + }; + } static Creator(value) { return config => { config.creator = value; @@ -651,6 +654,11 @@ class Wavelet { config.tag = value; }; } + static Payload(value) { + return config => { + config.payload = value; + }; + } static Id(value) { return config => { config.id = value; @@ -676,27 +684,27 @@ class Wavelet { config.onRoundPruned = fn; }; } - - static Payload(value) { - return config => { - config.payload = value; - }; - } static AccountUpdated(fn) { return config => { config.onAccountUpdated = fn; }; } + /** + * A client for interacting with the HTTP API of a Wavelet node. + * + * @param {string} host Address to the HTTP API of a Wavelet node. + * @param {Object=} opts Default options to be passed for making any HTTP request calls using this client instance (optional). + */ constructor(host, ...opts) { this.host = host; opts.forEach(opt => { - opt(this); + opt(this.http); }); - this.opts = { - ...this.opts, + this.http = { + ...this.http, transformRequest: [(data, headers) => { headers.common = {}; @@ -707,55 +715,68 @@ class Wavelet { /** * Query for information about the node you are connected to. - * - * @param {Object=} opts Options to be passed on for making the specified HTTP request call (optional). + ** http - Options to be passed on for making the specified HTTP request call (optional). + * @param {{http: Object=}} opts Options to be passed * @returns {Promise} */ - async getNodeInfo(opts) { - return (await axios.get(`${this.host}/ledger`, { ...this.opts, ...opts })).data; + async getNodeInfo(...opts) { + const config = { + http: {} + }; + opts.forEach(opt => opt(config)); + return (await axios.get(`${this.host}/ledger`, { ...this.http, ...config.http })).data; } /** * Query for details of a transaction. * * @param {string} id Hex-encoded transaction ID. - * @param {Object=} opts Options to be passed on for making the specified HTTP request call (optional). + ** http - Options to be passed on for making the specified HTTP request call (optional). + * @param {{http: Object=}} opts Options to be passed * @returns {Promise} */ async getTransaction(id, ...opts) { - const config = {}; + const config = { + http: {} + }; opts.forEach(opt => opt(config)); - return (await axios.get(`${this.host}/tx/${id}`, { ...this.opts, ...config })).data; + return (await axios.get(`${this.host}/tx/${id}`, { ...this.http, ...config.http })).data; } /** * Query for details of an account; whether it be a smart contract or a user. * * @param {string} id Hex-encoded account/smart contract address. - * @param {Object=} opts Options to be passed on for making the specified HTTP request call (optional). + ** http - Options to be passed on for making the specified HTTP request call (optional). + * @param {{http: Object=}} opts Options to be passed * @returns {Promise<{public_key: string, nonce: bigint, balance: bigint, stake: bigint, reward: bigint, is_contract: boolean, num_mem_pages: bigint}>} */ async getAccount(id, ...opts) { - const config = {}; + const config = { + http: {} + }; opts.forEach(opt => opt(config)); - return (await axios.get(`${this.host}/accounts/${id}`, { ...this.opts, ...config })).data; + return (await axios.get(`${this.host}/accounts/${id}`, { ...this.http, ...config.http })).data; } /** * Query for the raw WebAssembly code of a smart contract. * * @param string} id Hex-encoded ID of the smart contract. - * @param {Object=} opts Options to be passed on for making the specified HTTP request call (optional). + ** http - Options to be passed on for making the specified HTTP request call (optional). + * @param {{http: Object=}} opts Options to be passed * @returns {Promise} */ async getCode(id, ...opts) { - const config = {}; + const config = { + http: {} + }; opts.forEach(opt => opt(config)); return new Uint8Array((await axios.get(`${this.host}/contract/${id}`, { - ...this.opts, ...opts, + ...this.http, ...config.http, responseType: 'arraybuffer', responseEncoding: 'binary' })).data); @@ -771,7 +792,9 @@ class Wavelet { * initialize a WebAssembly VM with (either on browser/desktop). */ async getMemoryPages(id, num_mem_pages, ...opts) { - const config = {}; + const config = { + http: {} + }; opts.forEach(opt => opt(config)); if (num_mem_pages === 0) throw new Error("num pages cannot be zero"); @@ -783,7 +806,7 @@ class Wavelet { reqs.push((async () => { try { const res = await axios.get(`${this.host}/contract/${id}/page/${idx}`, { - ...this.opts, ...config, + ...this.http, ...config.http, responseType: 'arraybuffer', responseEncoding: 'binary' }); @@ -808,12 +831,13 @@ class Wavelet { * * @param {nacl.SignKeyPair} wallet * @param {string} recipient Hex-encoded recipient/smart contract address. - * @param {bigint} amount Amount of PERLs to send. - * @param {bigint=} gas_limit Gas limit to expend for invoking a smart contract function (optional). - * @param {bigint=} gas_deposit Amount of gas to deposit into a smart contract (optional). - * @param {string=} func_name Name of the function to invoke on a smart contract (optional). - * @param {Uint8Array=} func_payload Binary-serialized parameters to be used to invoke a smart contract function (optional). - * @param {Object=} opts Options to be passed on for making the specified HTTP request call (optional). + ** amount - Amount of PERLs to send. + ** gas_limit - Gas limit to expend for invoking a smart contract function (optional). + ** gas_deposit - Amount of gas to deposit into a smart contract (optional). + ** func_name - Name of the function to invoke on a smart contract (optional). + ** func_payload - Binary-serialized parameters to be used to invoke a smart contract function (optional). + ** http - Options to be passed on for making the specified HTTP request call (optional). + * @param {{func_payload: Uint8Array=, gas_deposit: bigint=, gas_limit: bigint=, amount: bigint=, http: Object=}}} opts Options to be passed on for making the specified HTTP request call (optional). * @returns {Promise} */ async transfer(wallet, recipient, ...opts) { @@ -832,12 +856,10 @@ class Wavelet { const { recipient, amount, - gas_deposit = 0, gas_limit = 0, func_payload = new Uint8Array(new ArrayBuffer(0)), - wallet, - ...opts + wallet } = config; let { func_name = "" } = config; @@ -863,47 +885,53 @@ class Wavelet { builder.writeBytes(func_payload_buf); } - return await this.sendTransaction(wallet, TAG_TRANSFER, builder.getBytes(), opts); + return await this.sendTransaction(wallet, TAG_TRANSFER, builder.getBytes(), config.http); } /** * Stake some amount of PERLs which is deducted from your wallets balance. * * @param {nacl.SignKeyPair} wallet Wavelet wallet. - * @param {bigint} amount Amount of PERLs to stake. - * @param {Object=} opts Options to be passed on for making the specified HTTP request call (optional). + ** amount - Amount of PERLs to place to your stake. + ** http - Options to be passed on for making the specified HTTP request call (optional). + * @param {{amount: bigint, http: Object=}} opts Options to be passed on for making the specified HTTP request call (optional). * @returns {Promise<*>} */ - async placeStake(wallet, amount, ...opts) { - const config = {}; + async placeStake(wallet, ...opts) { + const config = { + http: {} + }; opts.forEach(opt => opt(config)); const builder = new PayloadBuilder(); builder.writeByte(1); - builder.writeUint64(amount); + builder.writeUint64(config.amount); - return await this.sendTransaction(wallet, TAG_STAKE, builder.getBytes(), config); + return await this.sendTransaction(wallet, TAG_STAKE, builder.getBytes(), config.http); } /** * Withdraw stake, which is immediately converted into PERLS into your balance. * * @param {nacl.SignKeyPair} wallet Wavelet wallet. - * @param {bigint} amount Amount of PERLs to withdraw from your stake. - * @param {Object=} opts Options to be passed on for making the specified HTTP request call (optional). + ** amount - Amount of PERLs to withdraw from your stake. + ** http - Options to be passed on for making the specified HTTP request call (optional). + * @param {{amount: bigint, http: Object=}} opts Options to be passed on for making the specified HTTP request call (optional). * @returns {Promise<*>} */ - async withdrawStake(wallet, amount, ...opts) { - const config = {}; + async withdrawStake(wallet, ...opts) { + const config = { + http: {} + }; opts.forEach(opt => opt(config)); const builder = new PayloadBuilder(); builder.writeByte(0); - builder.writeUint64(amount); + builder.writeUint64(config.amount); - return await this.sendTransaction(wallet, TAG_STAKE, builder.getBytes(), config); + return await this.sendTransaction(wallet, TAG_STAKE, builder.getBytes(), config.http); } /** @@ -911,20 +939,23 @@ class Wavelet { * rounds will then convert into PERLs into your balance. * * @param {nacl.SignKeyPair} wallet Wavelet wallet. - * @param {bigint} amount Amount of PERLs to request to withdraw from your rewards. - * @param {Object=} opts Options to be passed on for making the specified HTTP request call (optional). + ** amount - Amount of PERLs to request to withdraw from your rewards. + ** http - Options to be passed on for making the specified HTTP request call (optional). + * @param {{amount: bigint, http: Object=}} opts Options to be passed on for making the specified HTTP request call (optional). * @returns {Promise<*>} */ - async withdrawReward(wallet, amount, ...opts) { - const config = {}; + async withdrawReward(wallet, ...opts) { + const config = { + http: {} + }; opts.forEach(opt => opt(config)); const builder = new PayloadBuilder(); builder.writeByte(2); - builder.writeUint64(amount); + builder.writeUint64(config.amount); - return await this.sendTransaction(wallet, TAG_STAKE, builder.getBytes(), config); + return await this.sendTransaction(wallet, TAG_STAKE, builder.getBytes(), config.http); } /** @@ -935,7 +966,8 @@ class Wavelet { ** gas_limit - Gas limit to expend for creating your smart contract, and invoking its init() function. ** gas_deposit - Amount of gas fees to deposit into a smart contract. ** params - Parameters to be used for invoking your smart contracts init() function. - * @param {{gas_limit: bigint, gas_deposit: bigint=, params:Object= }} opts + ** http - Options to be passed on for making the specified HTTP request call (optional). + * @param {{gas_limit: bigint, gas_deposit: bigint=, params: Object=, http: Object= }} opts * @returns {Promise<*>} */ async deployContract(wallet, code, ...opts) { @@ -946,7 +978,8 @@ class Wavelet { wallet, gas_deposit: JSBI.BigInt(0), gas_limit: JSBI.BigInt(0), - params: [] + params: [], + http: {} }; opts.forEach(opt => opt(config)); @@ -961,7 +994,7 @@ class Wavelet { builder.writeBytes(config.params); builder.writeBytes(code); - return await this.sendTransaction(wallet, TAG_CONTRACT, builder.getBytes(), config); + return await this.sendTransaction(wallet, TAG_CONTRACT, builder.getBytes(), config.http); } /** @@ -971,10 +1004,10 @@ class Wavelet { * @param {nacl.SignKeyPair} wallet Wavelet wallet. * @param {number} tag Tag of the transaction. * @param {Uint8Array} payload Binary payload of the transaction. - * @param {Object=} opts Options to be passed on for making the specified HTTP request call (optional). + * @param {Object=} http Options to be passed on for making the specified HTTP request call (optional). * @returns {Promise<*>} */ - async sendTransaction(wallet, tag, payload, opts = {}) { + async sendTransaction(wallet, tag, payload, http = {}) { const payload_hex = Buffer.from(payload).toString("hex"); const builder = new PayloadBuilder(); @@ -988,7 +1021,7 @@ class Wavelet { const req = { sender, tag, payload: payload_hex, signature }; - return (await axios.post(`${this.host}/tx/send`, JSON.stringify(req), { ...this.opts, ...opts })).data; + return (await axios.post(`${this.host}/tx/send`, JSON.stringify(req), { ...this.http, ...http })).data; } /** @@ -1246,7 +1279,7 @@ class Wavelet { const payload = Buffer.from(new Uint8Array(buf, offset, payloadLen)); offset += payloadLen; - transactions.push(this.parseTransaction(tag, payload)); + transactions.push(this.parseTransaction(Wavelet.Tag(tag), Wavelet.Payload(payload))); } return transactions; From 00625c1087288af1828b48db44c1fefa5e2b078d Mon Sep 17 00:00:00 2001 From: Claudiu Teodor Filip Date: Wed, 11 Sep 2019 13:38:18 +0300 Subject: [PATCH 5/8] refactor: applied functional options to sendTransactions --- src/main.js | 77 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 44 insertions(+), 33 deletions(-) diff --git a/src/main.js b/src/main.js index 018cdb2..fe6857a 100644 --- a/src/main.js +++ b/src/main.js @@ -700,7 +700,7 @@ class Wavelet { this.host = host; opts.forEach(opt => { - opt(this.http); + opt(this); }); this.http = { @@ -787,13 +787,14 @@ class Wavelet { * * @param {string} id Hex-encoded ID of the smart contract. * @param {number} num_mem_pages Number of memory pages the smart contract has. - * @param {Object=} opts Options to be passed on for making the specified HTTP request call (optional). + ** http - Options to be passed on for making the specified HTTP request call (optional). + * @param {{http: Object}} opts * @returns {Promise} The memory of the given smart contract, which may be used to * initialize a WebAssembly VM with (either on browser/desktop). */ async getMemoryPages(id, num_mem_pages, ...opts) { const config = { - http: {} + http: {} }; opts.forEach(opt => opt(config)); @@ -837,14 +838,15 @@ class Wavelet { ** func_name - Name of the function to invoke on a smart contract (optional). ** func_payload - Binary-serialized parameters to be used to invoke a smart contract function (optional). ** http - Options to be passed on for making the specified HTTP request call (optional). - * @param {{func_payload: Uint8Array=, gas_deposit: bigint=, gas_limit: bigint=, amount: bigint=, http: Object=}}} opts Options to be passed on for making the specified HTTP request call (optional). + * @param {{func_payload: Uint8Array=, gas_deposit: bigint=, gas_limit: bigint=, amount: bigint=, http: Object=}} opts * @returns {Promise} */ async transfer(wallet, recipient, ...opts) { const config = { recipient, - wallet + wallet, + http: {} }; opts.forEach(opt => opt(config)); return this._send(config); @@ -885,7 +887,7 @@ class Wavelet { builder.writeBytes(func_payload_buf); } - return await this.sendTransaction(wallet, TAG_TRANSFER, builder.getBytes(), config.http); + return await this.sendTransaction(wallet, Wavelet.Tag(TAG_TRANSFER), Wavelet.Payload(builder.getBytes()), Wavelet.Http(config.http)); } /** @@ -908,7 +910,7 @@ class Wavelet { builder.writeByte(1); builder.writeUint64(config.amount); - return await this.sendTransaction(wallet, TAG_STAKE, builder.getBytes(), config.http); + return await this.sendTransaction(wallet, Wavelet.Tag(TAG_STAKE), Wavelet.Payload(builder.getBytes()), Wavelet.Http(config.http)); } /** @@ -931,7 +933,7 @@ class Wavelet { builder.writeByte(0); builder.writeUint64(config.amount); - return await this.sendTransaction(wallet, TAG_STAKE, builder.getBytes(), config.http); + return await this.sendTransaction(wallet, Wavelet.Tag(TAG_STAKE), Wavelet.Payload(builder.getBytes()), Wavelet.Http(config.http)); } /** @@ -955,7 +957,7 @@ class Wavelet { builder.writeByte(2); builder.writeUint64(config.amount); - return await this.sendTransaction(wallet, TAG_STAKE, builder.getBytes(), config.http); + return await this.sendTransaction(wallet, Wavelet.Tag(TAG_STAKE), Wavelet.Payload(builder.getBytes()), Wavelet.Http(config.http)); } /** @@ -994,35 +996,44 @@ class Wavelet { builder.writeBytes(config.params); builder.writeBytes(code); - return await this.sendTransaction(wallet, TAG_CONTRACT, builder.getBytes(), config.http); + return await this.sendTransaction(wallet, Wavelet.Tag(TAG_CONTRACT), Wavelet.Payload(builder.getBytes()), Wavelet.Http(config.http)); } /** - * Send a transaction on behalf of a specified wallet with a designated - * tag and payload. - * - * @param {nacl.SignKeyPair} wallet Wavelet wallet. - * @param {number} tag Tag of the transaction. - * @param {Uint8Array} payload Binary payload of the transaction. - * @param {Object=} http Options to be passed on for making the specified HTTP request call (optional). - * @returns {Promise<*>} - */ - async sendTransaction(wallet, tag, payload, http = {}) { - const payload_hex = Buffer.from(payload).toString("hex"); - + * Send a transaction on behalf of a specified wallet with a designated + * tag and payload. + * + * @param {nacl.SignKeyPair} wallet Wavelet wallet. + ** tag - Tag of the transaction. + ** payload - Binary payload of the transaction. + ** http - Options to be passed on for making the specified HTTP request call (optional). + * @param {tag: number, payload: Uint8Array, http: Object=} opts + * @returns {Promise<*>} + */ + async sendTransaction(wallet, ...opts) { const builder = new PayloadBuilder(); + const config = { + http: {}, + sender: Buffer.from(wallet.publicKey).toString("hex"), + }; + + opts.forEach(opt => opt(config)); builder.writeUint64(BigInt(0)); - builder.writeByte(tag); - builder.writeBytes(payload); + builder.writeByte(config.tag); + builder.writeBytes(config.payload); + + const req = { + sender: config.sender, + tag: config.tag, + payload: Buffer.from(config.payload).toString("hex"), + signature: Buffer.from(nacl.sign.detached(builder.getBytes(), wallet.secretKey)).toString("hex") + }; - const signature = Buffer.from(nacl.sign.detached(builder.getBytes(), wallet.secretKey)).toString("hex"); - const sender = Buffer.from(wallet.publicKey).toString("hex"); + return (await axios.post(`${this.host}/tx/send`, JSON.stringify(req), { ...this.http, ...config.http })).data; + } - const req = { sender, tag, payload: payload_hex, signature }; - return (await axios.post(`${this.host}/tx/send`, JSON.stringify(req), { ...this.http, ...http })).data; - } /** * Poll for updates to accounts. @@ -1120,7 +1131,7 @@ class Wavelet { * @param {Object=} callback Callback function for each new event from the websocket. * @returns {Promise} Websocket client. */ - pollWebsocket(endpoint, params = {}, callback = {}) { + pollWebsocket(endpoint, params = {}, callback) { let info = url.parse(this.host); info.protocol = info.protocol === "https:" ? "wss:" : "ws:"; info.pathname = endpoint; @@ -1165,9 +1176,9 @@ class Wavelet { /** * Parse a transactions payload content into JSON. - * - * @param {(TAG_NOP|TAG_TRANSFER|TAG_CONTRACT|TAG_STAKE|TAG_BATCH)} tag Tag of a transaction. - * @param {string} payload Binary-serialized payload of a transaction. + ** tag - Tag of the transaction. + ** payload - Binary-serialized payload of a transaction. + * @param {{payload: string, tag: (TAG_NOP|TAG_TRANSFER|TAG_CONTRACT|TAG_STAKE|TAG_BATCH)}} otps * @returns {{amount: bigint, recipient: string}|{}|Array|{amount: bigint}} Decoded payload of a transaction. */ static parseTransaction(...opts) { From 146e367a5a85c78e3d4cbf0509f35b97f0663dba Mon Sep 17 00:00:00 2001 From: Claudiu Teodor Filip Date: Wed, 11 Sep 2019 14:29:55 +0300 Subject: [PATCH 6/8] fix: fixed deployContract function --- src/main.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main.js b/src/main.js index fe6857a..06c96fa 100644 --- a/src/main.js +++ b/src/main.js @@ -975,7 +975,6 @@ class Wavelet { async deployContract(wallet, code, ...opts) { const config = { - func_name, recipient: this.contract_id, wallet, gas_deposit: JSBI.BigInt(0), @@ -985,7 +984,7 @@ class Wavelet { }; opts.forEach(opt => opt(config)); - config.params = this.parseFunctionParams(...config.params); + config.params = new Uint8Array(config.params); code = new Uint8Array(code); const builder = new PayloadBuilder(); From 8e02ede357a714d871bc4c136e8bf3b60075a83c Mon Sep 17 00:00:00 2001 From: Claudiu Teodor Filip Date: Wed, 11 Sep 2019 14:31:23 +0300 Subject: [PATCH 7/8] feat: export PayloadBuilder --- src/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.js b/src/main.js index 06c96fa..c4eb408 100644 --- a/src/main.js +++ b/src/main.js @@ -1300,4 +1300,4 @@ class Wavelet { } } -export default { Wavelet, Contract, TAG_NOP, TAG_TRANSFER, TAG_CONTRACT, TAG_STAKE, TAG_BATCH, SetOption }; +export default { PayloadBuilder, Wavelet, Contract, TAG_NOP, TAG_TRANSFER, TAG_CONTRACT, TAG_STAKE, TAG_BATCH, SetOption }; From 60d3b970a56875a2e6b6bca6338e92aae24effa4 Mon Sep 17 00:00:00 2001 From: Claudiu Teodor Filip Date: Wed, 11 Sep 2019 14:37:40 +0300 Subject: [PATCH 8/8] feat: added flag to prevent actual transaction send and return the buil payload --- src/main.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main.js b/src/main.js index c4eb408..695d26d 100644 --- a/src/main.js +++ b/src/main.js @@ -1005,15 +1005,17 @@ class Wavelet { * @param {nacl.SignKeyPair} wallet Wavelet wallet. ** tag - Tag of the transaction. ** payload - Binary payload of the transaction. + ** dontSend - Flag to true to prevent request and get built payload ** http - Options to be passed on for making the specified HTTP request call (optional). - * @param {tag: number, payload: Uint8Array, http: Object=} opts + * @param {tag: number, payload: Uint8Array, dontSend: boolean, http: Object=} opts * @returns {Promise<*>} */ async sendTransaction(wallet, ...opts) { const builder = new PayloadBuilder(); const config = { http: {}, - sender: Buffer.from(wallet.publicKey).toString("hex"), + dontSend: false, + sender: Buffer.from(wallet.publicKey).toString("hex") }; opts.forEach(opt => opt(config)); @@ -1022,6 +1024,9 @@ class Wavelet { builder.writeByte(config.tag); builder.writeBytes(config.payload); + if (dontSend) { + return builder; + } const req = { sender: config.sender, tag: config.tag,