• R/O
  • HTTP
  • SSH
  • HTTPS

Bytom-JS-SDK: Commit

It is a project for Bytom Chrome extension JS SDK https://bytom.github.io/Bytom-JS-SDK


Commit MetaInfo

Revision2a7ce0006fefa9263634494c4214491ea81c24ff (tree)
Time2019-11-29 15:28:32
AuthorZhiting Lin <zlin035@uott...>
CommiterZhiting Lin

Log Message

update transactions

Change Summary

Incremental Difference

--- a/docs/sdk_transaction.js.html
+++ b/docs/sdk_transaction.js.html
@@ -41,7 +41,7 @@
4141
4242 <section>
4343 <article>
44- <pre class="prettyprint source linenums"><code>import {convertArgument, signTransaction1} from '../wasm/func';
44+ <pre class="prettyprint source linenums"><code>import {convertArgument, signTransaction} from '../wasm/func';
4545 import { handleApiError, handleAxiosError } from '../utils/http';
4646 import { getDB } from '../db/db';
4747 import keysSDK from "./keys";
@@ -205,7 +205,7 @@ transactionSDK.prototype.signTransaction = function(guid, transaction, password)
205205 }
206206 bytom.sdk.keys.getKeyByXPub(e.target.result.rootXPub).then(res => {
207207 let pm = {transaction: transaction, password: password, key: res};
208- signTransaction1(pm).then(res => {
208+ signTransaction(pm).then(res => {
209209 resolve(JSON.parse(res.data));
210210 }).catch(err => {
211211 reject(err);
--- a/src/api/accounts.js
+++ b/src/api/accounts.js
@@ -42,4 +42,30 @@ accountsApi.prototype.listAddresses = function(Guid) {
4242 return this.http.request('account/list-addresses', {Guid});
4343 };
4444
45+/**
46+ * Vapor API Copy Account.
47+ *
48+ * @param {Object} params - Parameters for address create.
49+ * @param {String} params.guid - AccountID,
50+ * @param {String} params.coin - Coin Type Api
51+ * @returns {Promise} Array of Object, with Guid, Address, label.
52+ */
53+accountsApi.prototype.copyAccount = function(params) {
54+ return this.http.request('account/copy', params);
55+};
56+
57+/**
58+ * Vapor API List Wallet.
59+ *
60+ * @param {Object} params - Parameters for Wallet List.
61+ * @param {String} params.start - start,
62+ * @param {String} params.limit - limit
63+ * @returns {Promise} Array of Object, with Guid, m, n, status, signers.
64+ */
65+accountsApi.prototype.copyAccount = function(params) {
66+ return this.http.request('account/list-wallets', params);
67+};
68+
69+
70+
4571 export default accountsApi;
\ No newline at end of file
--- a/src/http.js
+++ b/src/http.js
@@ -1,13 +1,13 @@
11 import axios from 'axios';
2-import {handleApiError} from './utils/http';
2+import {handleApiError, handleAxiosError} from './utils/http';
33
4-const basePath = 'api/v1/btm/';
4+// const basePath = 'api/v1/btm';
55
66 export function serverHttp(host) {
77 this.host = host;
88 this.request = function(path, body, net, method) {
99 var config = {
10- url: this.host[net] ? `${this.host[net]}${basePath}${path}`: `${this.host}${basePath}${path}`,
10+ url: this.host[net] ? `${this.host[net]}${path}`: `${this.host}${path}`,
1111 method: method ? method : 'POST' ,
1212 headers: {
1313 Accept: 'application/json',
@@ -17,7 +17,17 @@ export function serverHttp(host) {
1717 };
1818
1919 //return Promise
20- return axios.request(config);
20+ return axios.request(config)
21+ .then(function(resp){
22+ if (resp.status !== 200 || resp.data.code !== 200) {
23+ throw handleApiError(resp);
24+ } else if (resp.data.code === 200) {
25+ return resp.data.result.data;
26+ }
27+ return resp.data;
28+ }).catch(error=>{
29+ throw handleAxiosError(error);
30+ });
2131 };
2232 }
2333
@@ -25,7 +35,7 @@ export function http(baseUrl) {
2535 this.baseUrl = baseUrl;
2636 this.request = function(path, body, method) {
2737 var config = {
28- url: `${this.baseUrl}${basePath}${path}`,
38+ url: `${this.baseUrl}${path}`,
2939 method: method ? method : 'POST' ,
3040 headers: {
3141 Accept: 'application/json',
--- a/src/sdk/accounts.js
+++ b/src/sdk/accounts.js
@@ -22,6 +22,7 @@ accountsSDK.prototype.listAccountUseServer = function() {
2222 let keyRange = IDBKeyRange.only(net);
2323 let oc = objectStore.openCursor(keyRange);
2424 let ret = [];
25+
2526 oc.onsuccess = function (event) {
2627 var cursor = event.target.result;
2728 if (cursor) {
@@ -51,14 +52,7 @@ accountsSDK.prototype.listAccountUseServer = function() {
5152 */
5253 accountsSDK.prototype.listAddressUseServer = function(guid) {
5354 let net = this.bytom.net;
54- let retPromise = new Promise((resolve, reject) => {
55- this.http.request('account/list-addresses', {guid:guid}, net).then(resp => {
56- resolve(resp.data.result.data);
57- }).catch(error => {
58- reject(handleAxiosError(error));
59- });
60- });
61- return retPromise;
55+ return this.http.request('account/list-addresses', {guid:guid}, net);
6256 };
6357 /**
6458 * Create a new address for a wallet.
@@ -76,11 +70,7 @@ accountsSDK.prototype.createAccountReceiverUseServer = function(guid, label) {
7670 pm.label = label;
7771 }
7872 this.http.request('account/new-address', pm, net).then(resp => {
79- if (resp.status !== 200 || resp.data.code !== 200) {
80- reject(handleApiError(resp));
81- return;
82- }
83- let dbData = resp.data.result.data;
73+ let dbData = resp;
8474 dbData.guid = guid;
8575 dbData.net = net;
8676 getDB().then(db => {
@@ -130,11 +120,7 @@ accountsSDK.prototype.createAccountUseServer = function(rootXPub, alias, label)
130120 pm.label = label;
131121 }
132122 that.http.request('account/create', pm, net).then(resp => {
133- if (resp.status !== 200 || resp.data.code !== 200) {
134- reject(handleApiError(resp));
135- return;
136- }
137- let dbData = resp.data.result.data;
123+ let dbData = resp;
138124 dbData.rootXPub = rootXPub;
139125 dbData.alias = alias;
140126 dbData.net = net;
@@ -173,6 +159,103 @@ accountsSDK.prototype.createAccountUseServer = function(rootXPub, alias, label)
173159 };
174160
175161 /**
162+ * Create a wallet using a public key. Each wallet is identified by a guid. (by server)
163+ *
164+ * @param {String} guid
165+ * @param {String} coin type of coin
166+ * @returns {Promise}
167+ */
168+accountsSDK.prototype.copyAccountUseServer = function(guid, coin) {
169+ let net = this.bytom.net;
170+ let that = this;
171+ let retPromise = new Promise((resolve, reject) => {
172+ let pm = {guid};
173+ if (coin) {
174+ pm.coin = coin;
175+ }
176+
177+ that.http.request('account/copy', pm, net).then(resp => {
178+ getDB().then(db => {
179+ let objectStore = db.transaction(['accounts-server'], 'readwrite').objectStore('accounts-server');
180+ let index = objectStore.index('guid');
181+ let keyRange = IDBKeyRange.only(guid);
182+ let getRequest = index.openCursor(keyRange);
183+
184+ getRequest.onsuccess = function(e) {
185+ const cursor = e.target.result;
186+ if(cursor){
187+ const accountObject = cursor.value;
188+
189+ accountObject.vpAddress = resp.address;
190+ const request = cursor.update(accountObject);
191+ request.onsuccess = function () {
192+ resolve(accountObject);
193+ };
194+ request.onerror = function () {
195+ reject(request.error);
196+ };
197+ }
198+ };
199+ getRequest.onerror = function() {
200+ reject(getRequest.error);
201+ };
202+ }).catch(err => {
203+ throw (err);
204+ });
205+ }).catch(err => {
206+ reject(err);
207+ });
208+ });
209+ return retPromise;
210+};
211+
212+/**
213+ * list a wallet using a guid. Each wallet is identified by a guid. (by server)
214+ *
215+ * @param {String} guid
216+ * @param {String} coin type of coin
217+ * @returns {Promise}
218+ */
219+accountsSDK.prototype.listVaporAccountUseServer = function(guid) {
220+ let net = this.bytom.net;
221+ let that = this;
222+ let retPromise = new Promise((resolve, reject) => {
223+ that.http.request('account/list-addresses', {guid:guid}, net).then(resp => {
224+ getDB().then(db => {
225+ let objectStore = db.transaction(['accounts-server'], 'readwrite').objectStore('accounts-server');
226+ let index = objectStore.index('guid');
227+ let keyRange = IDBKeyRange.only(guid);
228+ let getRequest = index.openCursor(keyRange);
229+
230+ getRequest.onsuccess = function(e) {
231+ const cursor = e.target.result;
232+ if(cursor){
233+ const accountObject = cursor.value;
234+
235+ accountObject.vpAddress = resp[0].address;
236+ const request = cursor.update(accountObject);
237+ request.onsuccess = function () {
238+ resolve(accountObject);
239+ };
240+ request.onerror = function () {
241+ reject(request.error);
242+ };
243+ }
244+ };
245+ getRequest.onerror = function() {
246+ reject(getRequest.error);
247+ };
248+ }).catch(err => {
249+ throw (err);
250+ });
251+ }).catch(err => {
252+ reject(err);
253+ });
254+ });
255+ return retPromise;
256+};
257+
258+/**
176259 * create account
177260 *
178261 * @param {String} alias
--- a/src/sdk/keys.js
+++ b/src/sdk/keys.js
@@ -1,4 +1,4 @@
1-import {createKey, resetKeyPassword, createPubkey} from '../wasm/func';
1+import {createKey, resetKeyPassword, createPubkey, signMessage, signTransaction} from '../wasm/func';
22 import {getDB} from '../db/db';
33
44
@@ -183,4 +183,62 @@ keysSDK.prototype.createPubkey = function(xpub) {
183183 return retPromise;
184184 };
185185
186+/**
187+ * Sign Message.
188+ *
189+ * @param {String} message - message.
190+ * @param {String} password - password.
191+ * @param {Object} address - address.
192+ */
193+keysSDK.prototype.signMessage = function(message, password, address) {
194+ let retPromise = new Promise((resolve, reject) => {
195+ getDB().then(db => {
196+ let getRequest = db.transaction(['accounts-server'], 'readonly')
197+ .objectStore('accounts-server')
198+ .getAll()
199+
200+ getRequest.onsuccess = function (e) {
201+ const result = getRequest.result.filter(obj => obj.address === address)
202+ if (result.length === 0) {
203+ reject(new Error('not found address'));
204+ return;
205+ }
206+
207+ const rootXpub = result[0].rootXPub
208+ let keyObject = db.transaction(['keys'], 'readonly')
209+ .objectStore('keys')
210+ .index('xpub')
211+ .get(rootXpub);
212+
213+ keyObject.onsuccess = function (e) {
214+ if (!e.target.result) {
215+ reject(new Error('not found xpub'));
216+ return;
217+ }
218+
219+ let data = {};
220+ data.message = message;
221+ data.password = password;
222+ data.key = e.target.result.key;
223+ signMessage(data).then((res) => {
224+ let jsonData = JSON.parse(res.data);
225+ resolve(jsonData);
226+ }).catch(error => {
227+ reject(error);
228+ });
229+ };
230+ keyObject.onerror = function () {
231+ reject(getRequest.error);
232+ };
233+ };
234+ getRequest.onerror = function () {
235+ reject(getRequest.error);
236+ };
237+ }).catch(error => {
238+ reject(error);
239+ });
240+ });
241+ return retPromise;
242+};
243+
186244 export default keysSDK;
\ No newline at end of file
--- a/src/sdk/query.js
+++ b/src/sdk/query.js
@@ -1,5 +1,3 @@
1-import { handleAxiosError } from '../utils/http';
2-
31 function querySDK(bytom) {
42 this.bytom =bytom;
53 this.http = bytom.serverHttp;
@@ -11,14 +9,7 @@ function querySDK(bytom) {
119 */
1210 querySDK.prototype.asset = function(asset_id) {
1311 let net = this.bytom.net;
14- let retPromise = new Promise((resolve, reject) => {
15- this.http.request('q/asset?id=' + asset_id, null, net, 'GET').then(resp => {
16- resolve(resp.data);
17- }).catch(err => {
18- reject(handleAxiosError(err));
19- });
20- });
21- return retPromise;
12+ return this.http.request('q/asset?id=' + asset_id, null, net, 'GET');
2213 };
2314
2415 /**
@@ -26,14 +17,7 @@ querySDK.prototype.asset = function(asset_id) {
2617 */
2718 querySDK.prototype.getblockcount = function() {
2819 let net = this.bytom.net;
29- let retPromise = new Promise((resolve, reject) => {
30- this.http.request('q/chain-status', null, net, 'GET').then(resp => {
31- resolve(resp.data);
32- }).catch(err => {
33- reject(handleAxiosError(err));
34- });
35- });
36- return retPromise;
20+ return this.http.request('q/chain-status', null, net, 'GET');
3721 };
3822
3923 /**
@@ -41,14 +25,16 @@ querySDK.prototype.getblockcount = function() {
4125 */
4226 querySDK.prototype.listUtxo = function(object) {
4327 let net = this.bytom.net;
44- let retPromise = new Promise((resolve, reject) => {
45- this.http.request('q/list-utxos',object, net, 'POST').then(resp => {
46- resolve(resp.data);
47- }).catch(err => {
48- reject(handleAxiosError(err));
49- });
50- });
51- return retPromise;
28+ return this.http.request('q/list-utxos',object, net, 'POST');
29+};
30+
31+/**
32+ * Query the vote status.
33+ * vapor only
34+ */
35+querySDK.prototype.getVoteStatus = function() {
36+ let net = this.bytom.net;
37+ return this.http.request('q/get-vote-status',null, net, 'GET');
5238 };
5339
5440 export default querySDK;
\ No newline at end of file
--- a/src/sdk/transaction.js
+++ b/src/sdk/transaction.js
@@ -1,7 +1,6 @@
1-import {convertArgument, signTransaction1} from '../wasm/func';
1+import {convertArgument, signTransaction} from '../wasm/func';
22 import { handleApiError, handleAxiosError } from '../utils/http';
33 import { getDB } from '../db/db';
4-import keysSDK from "./keys";
54
65 function transactionSDK(bytom) {
76 this.http = bytom.serverHttp;
@@ -14,34 +13,34 @@ function transactionSDK(bytom) {
1413 *
1514 * @see https://gist.github.com/HAOYUatHZ/0c7446b8f33e7cddd590256b3824b08f#apiv1btmmerchantlist-transactions
1615 * @param {String} guid unique id for each wallet
17- * @param {String} address (optional) if provided, will only return transactions the address is related to
16+ * @param {String} filter (optional) if provided, will only return transactions the filter condition is related to
17+ * @param {String} sort (optional) if provided, will only return transactions the sort condition is related to
1818 * @param {Number} start page start
1919 * @param {Number} limit page limit
2020 * @returns {Promise}
2121 */
22-transactionSDK.prototype.list = function(guid, address, start, limit) {
22+transactionSDK.prototype.list = function(guid, filter,sort, start, limit) {
2323 let net = this.bytom.net;
24- let retPromise = new Promise((resolve, reject) => {
25- let pm = {guid: guid};
26- if (address) {
27- pm.address = address;
28- }
29- let url = 'merchant/list-transactions';
30- let args = new URLSearchParams();
31- if (typeof start !== 'undefined') {
32- args.append('start', start);
33- }
34- if (limit) {
35- args.append('limit', limit);
36- }
37- url = url + '?' + args.toString();
38- this.http.request(url, pm, net).then(resp => {
39- resolve(resp.data);
40- }).catch(err => {
41- reject(handleAxiosError(err));
42- });
43- });
44- return retPromise;
24+ let pm = {guid: guid};
25+
26+ if (filter) {
27+ pm.filter = filter;
28+ }
29+
30+ if (sort) {
31+ pm.sort = sort;
32+ }
33+
34+ let url = 'merchant/list-transactions';
35+ let args = new URLSearchParams();
36+ if (typeof start !== 'undefined') {
37+ args.append('start', start);
38+ }
39+ if (limit) {
40+ args.append('limit', limit);
41+ }
42+ url = url + '?' + args.toString();
43+ return this.http.request(url, pm, net);
4544 };
4645
4746 /**
@@ -54,19 +53,8 @@ transactionSDK.prototype.list = function(guid, address, start, limit) {
5453 */
5554 transactionSDK.prototype.submitPayment = function(guid, raw_transaction, signatures) {
5655 let net = this.bytom.net;
57- let retPromise = new Promise((resolve, reject) => {
58- let pm = {guid: guid, raw_transaction: raw_transaction, signatures: signatures};
59- this.http.request('merchant/submit-payment', pm, net).then(resp => {
60- if (resp.status !== 200 || resp.data.code !== 200) {
61- reject(handleApiError(resp));
62- return;
63- }
64- resolve(resp.data);
65- }).catch(err => {
66- reject(handleAxiosError(err));
67- });
68- });
69- return retPromise;
56+ let pm = {guid: guid, raw_transaction: raw_transaction, signatures: signatures};
57+ return this.http.request('merchant/submit-payment', pm, net);
7058 };
7159
7260 /**
@@ -82,27 +70,111 @@ transactionSDK.prototype.submitPayment = function(guid, raw_transaction, signatu
8270 * @param {Number} confirmations - transaction confirmations
8371 * @returns {Promise}
8472 */
85-transactionSDK.prototype.buildPayment = function(guid, to, asset, amount, fee, confirmations) {
73+transactionSDK.prototype.buildPayment = function(guid, to, asset, amount, fee, confirmations, memo, forbidChainTx) {
8674 let net = this.bytom.net;
87- let retPromise = new Promise((resolve, reject) => {
88- let pm = {guid: guid, to: to, asset: asset, amount: amount};
89- if (fee) {
90- pm.fee = fee;
91- }
92- if (confirmations) {
93- pm.confirmations = confirmations;
94- }
95- this.http.request('merchant/build-payment', pm, net).then(resp => {
96- if (resp.status !== 200 || resp.data.code !== 200) {
97- reject(handleApiError(resp));
98- return;
99- }
100- resolve(resp.data);
101- }).catch(err => {
102- reject(handleAxiosError(err));
103- });
104- });
105- return retPromise;
75+ let pm = {
76+ guid: guid,
77+ asset: asset,
78+ recipients: {},
79+ forbid_chain_tx: false
80+ };
81+
82+ pm['recipients'][`${to}`] = amount
83+
84+ if (memo) {
85+ pm.memo = memo;
86+ }
87+ if (forbidChainTx) {
88+ pm.forbid_chain_tx = forbidChainTx;
89+ }
90+ if (fee) {
91+ pm.fee = fee;
92+ }
93+ if (confirmations) {
94+ pm.confirmations = confirmations;
95+ }
96+ return this.http.request('merchant/build-payment', pm, net);
97+};
98+
99+/**
100+ * Build a cross chain transaction.
101+ *
102+ * @param {String} guid unique id for each wallet
103+ * @param {String} to destination address
104+ * @param {String} asset hexdecimal asset id
105+ * @param {Number} amount transfer amount
106+ * @param {Number} confirmations - transaction confirmations
107+ * @returns {Promise}
108+ */
109+transactionSDK.prototype.buildCrossChain = function(guid, to, asset, amount, confirmations, forbidChainTx) {
110+ let net = this.bytom.net;
111+
112+ let pm = {
113+ guid: guid,
114+ asset: asset,
115+ recipients: {},
116+ forbid_chain_tx: false
117+ };
118+
119+ pm['recipients'][`${to}`] = amount
120+
121+ if (forbidChainTx) {
122+ pm.forbid_chain_tx = forbidChainTx;
123+ }
124+
125+ return this.http.request('merchant/build-crosschain', pm, net);
126+};
127+
128+/**
129+ * Build a Vote transaction.
130+ *
131+ * @param {String} guid unique id for each wallet
132+ * @param {String} vote pubkey vote
133+ * @param {String} memo memo key
134+ * @param {Number} amount transfer amount
135+ * @param {Number} confirmations - transaction confirmations
136+ * @returns {Promise}
137+ */
138+transactionSDK.prototype.buildVote = function(guid, vote, amount, confirmations, memo, forbidChainTx) {
139+ let net = this.bytom.net;
140+ let pm = {guid, vote, amount: amount, forbid_chain_tx: false};
141+ if (confirmations) {
142+ pm.confirmations = confirmations;
143+ }
144+ if (memo) {
145+ pm.memo = memo;
146+ }
147+ if (forbidChainTx) {
148+ pm.forbid_chain_tx = forbidChainTx;
149+ }
150+
151+ return this.http.request('merchant/build-vote', pm, net);
152+};
153+
154+/**
155+ * Build a Veto transaction.
156+ *
157+ * @param {String} guid unique id for each wallet
158+ * @param {String} vote pubkey vote
159+ * @param {String} memo memo key
160+ * @param {Number} amount transfer amount
161+ * @param {Number} confirmations - transaction confirmations
162+ * @returns {Promise}
163+ */
164+transactionSDK.prototype.buildVeto = function(guid, vote, amount, confirmations, memo, forbidChainTx) {
165+ let net = this.bytom.net;
166+ let pm = {guid, vote, amount: amount, forbid_chain_tx: false};
167+ if (confirmations) {
168+ pm.confirmations = confirmations;
169+ }
170+ if (memo) {
171+ pm.memo = memo;
172+ }
173+ if (forbidChainTx) {
174+ pm.forbid_chain_tx = forbidChainTx;
175+ }
176+
177+ return this.http.request('merchant/build-veto', pm, net);
106178 };
107179
108180 /**
@@ -115,29 +187,18 @@ transactionSDK.prototype.buildPayment = function(guid, to, asset, amount, fee, c
115187 */
116188 transactionSDK.prototype.buildTransaction = function(guid, inputs, outputs, fee, confirmations ) {
117189 let net = this.bytom.net;
118- let retPromise = new Promise((resolve, reject) => {
119- let pm = {
120- guid,
121- inputs,
122- outputs,
123- };
124- if (fee) {
125- pm.fee = fee;
126- }
127- if (confirmations) {
128- pm.confirmations = confirmations;
129- }
130- this.http.request('merchant/build-transaction', pm, net).then(resp => {
131- if (resp.status !== 200 || resp.data.code !== 200) {
132- reject(handleApiError(resp));
133- return;
134- }
135- resolve(resp.data);
136- }).catch(err => {
137- reject(handleAxiosError(err));
138- });
139- });
140- return retPromise;
190+ let pm = {
191+ guid,
192+ inputs,
193+ outputs,
194+ };
195+ if (fee) {
196+ pm.fee = fee;
197+ }
198+ if (confirmations) {
199+ pm.confirmations = confirmations;
200+ }
201+ return this.http.request('merchant/build-transaction', pm, net);
141202 };
142203
143204 /**
@@ -162,7 +223,7 @@ transactionSDK.prototype.signTransaction = function(guid, transaction, password)
162223 }
163224 bytom.sdk.keys.getKeyByXPub(e.target.result.rootXPub).then(res => {
164225 let pm = {transaction: transaction, password: password, key: res};
165- signTransaction1(pm).then(res => {
226+ signTransaction(pm).then(res => {
166227 resolve(JSON.parse(res.data));
167228 }).catch(err => {
168229 reject(err);
--- a/src/wasm/func.js
+++ b/src/wasm/func.js
@@ -47,24 +47,13 @@ export async function resetKeyPassword(data) {
4747 return res;
4848 }
4949
50-//signTransaction bytom node standard
51-export async function signTransaction(data) {
52- await init();
53- let res = newWasmResult();
54- window.AllFunc.signTransaction(data, res);
55- await res.wait;
56- if (res.hasOwnProperty('error')) {
57- throw new Error(res.error);
58- }
59- return res;
60-}
61-//signTransaction1 bytom central server standard
50+//signTransaction bytom central server standard
6251 //see https://gist.github.com/HAOYUatHZ/0c7446b8f33e7cddd590256b3824b08f#apiv1btmmerchantsubmit-payment
6352 //see https://github.com/Bytom-Community/Bytom-WebAssembly/blob/master/sdk/transaction.go (wasm implement)
64-export async function signTransaction1(data) {
53+export async function signTransaction(data) {
6554 await init();
6655 let res = newWasmResult();
67- window.AllFunc.signTransaction1(data, res);
56+ window.AllFunc.signTransaction(data, res);
6857 await res.wait;
6958 if (res.hasOwnProperty('error')) {
7059 throw new Error(res.error);
@@ -116,6 +105,17 @@ export async function createPubkey(data) {
116105 return res;
117106 }
118107
108+export async function signMessage(data) {
109+ await init();
110+ let res = newWasmResult();
111+ window.AllFunc.signMessage(data, res);
112+ await res.wait;
113+ if (res.hasOwnProperty('error')) {
114+ throw new Error(res.error);
115+ }
116+ return res;
117+}
118+
119119 export async function convertArgument(data) {
120120 await init();
121121 let res = newWasmResult();
--- a/src/wasm/go.js
+++ b/src/wasm/go.js
@@ -1,393 +1,417 @@
1-/*eslint-disable*/
21 // Copyright 2018 The Go Authors. All rights reserved.
32 // Use of this source code is governed by a BSD-style
43 // license that can be found in the LICENSE file.
5-//see https://github.com/golang/go/wiki/WebAssembly
4+
65 export function LoadWasm() {
7- // Map web browser API and Node.js API to a single common API (preferring web standards over Node.js API).
8- if (typeof window !== "undefined") {
9- window.global = window;
10- } else if (typeof self !== "undefined") {
11- self.global = self;
12- } else {
13- throw new Error("cannot export Go (neither window nor self is defined)");
14- }
15-
16- let outputBuf = "";
17- global.fs = {
18- constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused
19- writeSync(fd, buf) {
20- outputBuf += decoder.decode(buf);
21- const nl = outputBuf.lastIndexOf("\n");
22- if (nl != -1) {
23- console.log(outputBuf.substr(0, nl));
24- outputBuf = outputBuf.substr(nl + 1);
25- }
26- return buf.length;
27- },
28- openSync(path, flags, mode) {
29- const err = new Error("not implemented");
30- err.code = "ENOSYS";
31- throw err;
32- },
33- };
34-
35- const encoder = new TextEncoder("utf-8");
36- const decoder = new TextDecoder("utf-8");
37-
38- global.Go = class {
39- constructor() {
40- this.argv = ["js"];
41- this.env = {};
42- this.exit = (code) => {
43- if (code !== 0) {
44- console.warn("exit code:", code);
45- }
46- if(typeof window.resetWasmStatus == "function") {
47- window.resetWasmStatus();
48- }
49- };
50- this._callbackTimeouts = new Map();
51- this._nextCallbackTimeoutID = 1;
52-
53- const mem = () => {
54- // The buffer may change when requesting more memory.
55- return new DataView(this._inst.exports.mem.buffer);
56- }
57-
58- const setInt64 = (addr, v) => {
59- mem().setUint32(addr + 0, v, true);
60- mem().setUint32(addr + 4, Math.floor(v / 4294967296), true);
61- }
62-
63- const getInt64 = (addr) => {
64- const low = mem().getUint32(addr + 0, true);
65- const high = mem().getInt32(addr + 4, true);
66- return low + high * 4294967296;
67- }
68-
69- const loadValue = (addr) => {
70- const f = mem().getFloat64(addr, true);
71- if (!isNaN(f)) {
72- return f;
73- }
74-
75- const id = mem().getUint32(addr, true);
76- return this._values[id];
77- }
78-
79- const storeValue = (addr, v) => {
80- const nanHead = 0x7FF80000;
81-
82- if (typeof v === "number") {
83- if (isNaN(v)) {
84- mem().setUint32(addr + 4, nanHead, true);
85- mem().setUint32(addr, 0, true);
86- return;
87- }
88- mem().setFloat64(addr, v, true);
89- return;
90- }
91-
92- switch (v) {
93- case undefined:
94- mem().setUint32(addr + 4, nanHead, true);
95- mem().setUint32(addr, 1, true);
96- return;
97- case null:
98- mem().setUint32(addr + 4, nanHead, true);
99- mem().setUint32(addr, 2, true);
100- return;
101- case true:
102- mem().setUint32(addr + 4, nanHead, true);
103- mem().setUint32(addr, 3, true);
104- return;
105- case false:
106- mem().setUint32(addr + 4, nanHead, true);
107- mem().setUint32(addr, 4, true);
108- return;
109- }
110-
111- let ref = this._refs.get(v);
112- if (ref === undefined) {
113- ref = this._values.length;
114- this._values.push(v);
115- this._refs.set(v, ref);
116- }
117- let typeFlag = 0;
118- switch (typeof v) {
119- case "string":
120- typeFlag = 1;
121- break;
122- case "symbol":
123- typeFlag = 2;
124- break;
125- case "function":
126- typeFlag = 3;
127- break;
128- }
129- mem().setUint32(addr + 4, nanHead | typeFlag, true);
130- mem().setUint32(addr, ref, true);
131- }
132-
133- const loadSlice = (addr) => {
134- const array = getInt64(addr + 0);
135- const len = getInt64(addr + 8);
136- return new Uint8Array(this._inst.exports.mem.buffer, array, len);
137- }
138-
139- const loadSliceOfValues = (addr) => {
140- const array = getInt64(addr + 0);
141- const len = getInt64(addr + 8);
142- const a = new Array(len);
143- for (let i = 0; i < len; i++) {
144- a[i] = loadValue(array + i * 8);
145- }
146- return a;
147- }
148-
149- const loadString = (addr) => {
150- const saddr = getInt64(addr + 0);
151- const len = getInt64(addr + 8);
152- return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len));
153- }
154-
155- const timeOrigin = Date.now() - performance.now();
156- this.importObject = {
157- go: {
158- // func wasmExit(code int32)
159- "runtime.wasmExit": (sp) => {
160- const code = mem().getInt32(sp + 8, true);
161- this.exited = true;
162- delete this._inst;
163- delete this._values;
164- delete this._refs;
165- this.exit(code);
166- },
167-
168- // func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
169- "runtime.wasmWrite": (sp) => {
170- const fd = getInt64(sp + 8);
171- const p = getInt64(sp + 16);
172- const n = mem().getInt32(sp + 24, true);
173- fs.writeSync(fd, new Uint8Array(this._inst.exports.mem.buffer, p, n));
174- },
175-
176- // func nanotime() int64
177- "runtime.nanotime": (sp) => {
178- setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000);
179- },
180-
181- // func walltime() (sec int64, nsec int32)
182- "runtime.walltime": (sp) => {
183- const msec = (new Date).getTime();
184- setInt64(sp + 8, msec / 1000);
185- mem().setInt32(sp + 16, (msec % 1000) * 1000000, true);
186- },
187-
188- // func scheduleCallback(delay int64) int32
189- "runtime.scheduleCallback": (sp) => {
190- const id = this._nextCallbackTimeoutID;
191- this._nextCallbackTimeoutID++;
192- this._callbackTimeouts.set(id, setTimeout(
193- () => { this._resolveCallbackPromise(); },
194- getInt64(sp + 8) + 1, // setTimeout has been seen to fire up to 1 millisecond early
195- ));
196- mem().setInt32(sp + 16, id, true);
197- },
198-
199- // func clearScheduledCallback(id int32)
200- "runtime.clearScheduledCallback": (sp) => {
201- const id = mem().getInt32(sp + 8, true);
202- clearTimeout(this._callbackTimeouts.get(id));
203- this._callbackTimeouts.delete(id);
204- },
205-
206- // func getRandomData(r []byte)
207- "runtime.getRandomData": (sp) => {
208- crypto.getRandomValues(loadSlice(sp + 8));
209- },
210-
211- // func stringVal(value string) ref
212- "syscall/js.stringVal": (sp) => {
213- storeValue(sp + 24, loadString(sp + 8));
214- },
215-
216- // func valueGet(v ref, p string) ref
217- "syscall/js.valueGet": (sp) => {
218- storeValue(sp + 32, Reflect.get(loadValue(sp + 8), loadString(sp + 16)));
219- },
220-
221- // func valueSet(v ref, p string, x ref)
222- "syscall/js.valueSet": (sp) => {
223- Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32));
224- },
225-
226- // func valueIndex(v ref, i int) ref
227- "syscall/js.valueIndex": (sp) => {
228- storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16)));
229- },
230-
231- // valueSetIndex(v ref, i int, x ref)
232- "syscall/js.valueSetIndex": (sp) => {
233- Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24));
234- },
235-
236- // func valueCall(v ref, m string, args []ref) (ref, bool)
237- "syscall/js.valueCall": (sp) => {
238- try {
239- const v = loadValue(sp + 8);
240- const m = Reflect.get(v, loadString(sp + 16));
241- const args = loadSliceOfValues(sp + 32);
242- storeValue(sp + 56, Reflect.apply(m, v, args));
243- mem().setUint8(sp + 64, 1);
244- } catch (err) {
245- storeValue(sp + 56, err);
246- mem().setUint8(sp + 64, 0);
247- }
248- },
249-
250- // func valueInvoke(v ref, args []ref) (ref, bool)
251- "syscall/js.valueInvoke": (sp) => {
252- try {
253- const v = loadValue(sp + 8);
254- const args = loadSliceOfValues(sp + 16);
255- storeValue(sp + 40, Reflect.apply(v, undefined, args));
256- mem().setUint8(sp + 48, 1);
257- } catch (err) {
258- storeValue(sp + 40, err);
259- mem().setUint8(sp + 48, 0);
260- }
261- },
262-
263- // func valueNew(v ref, args []ref) (ref, bool)
264- "syscall/js.valueNew": (sp) => {
265- try {
266- const v = loadValue(sp + 8);
267- const args = loadSliceOfValues(sp + 16);
268- storeValue(sp + 40, Reflect.construct(v, args));
269- mem().setUint8(sp + 48, 1);
270- } catch (err) {
271- storeValue(sp + 40, err);
272- mem().setUint8(sp + 48, 0);
273- }
274- },
275-
276- // func valueLength(v ref) int
277- "syscall/js.valueLength": (sp) => {
278- setInt64(sp + 16, parseInt(loadValue(sp + 8).length));
279- },
280-
281- // valuePrepareString(v ref) (ref, int)
282- "syscall/js.valuePrepareString": (sp) => {
283- const str = encoder.encode(String(loadValue(sp + 8)));
284- storeValue(sp + 16, str);
285- setInt64(sp + 24, str.length);
286- },
287-
288- // valueLoadString(v ref, b []byte)
289- "syscall/js.valueLoadString": (sp) => {
290- const str = loadValue(sp + 8);
291- loadSlice(sp + 16).set(str);
292- },
293-
294- // func valueInstanceOf(v ref, t ref) bool
295- "syscall/js.valueInstanceOf": (sp) => {
296- mem().setUint8(sp + 24, loadValue(sp + 8) instanceof loadValue(sp + 16));
297- },
298-
299- "debug": (value) => {
300- console.log(value);
301- },
302- }
303- };
304- }
305-
306- async run(instance) {
307- this._inst = instance;
308- this._values = [ // TODO: garbage collection
309- NaN,
310- undefined,
311- null,
312- true,
313- false,
314- global,
315- this._inst.exports.mem,
316- this,
317- ];
318- this._refs = new Map();
319- this._callbackShutdown = false;
320- this.exited = false;
321-
322- const mem = new DataView(this._inst.exports.mem.buffer)
323-
324- // Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory.
325- let offset = 4096;
326-
327- const strPtr = (str) => {
328- let ptr = offset;
329- new Uint8Array(mem.buffer, offset, str.length + 1).set(encoder.encode(str + "\0"));
330- offset += str.length + (8 - (str.length % 8));
331- return ptr;
332- };
333-
334- const argc = this.argv.length;
335-
336- const argvPtrs = [];
337- this.argv.forEach((arg) => {
338- argvPtrs.push(strPtr(arg));
339- });
340-
341- const keys = Object.keys(this.env).sort();
342- argvPtrs.push(keys.length);
343- keys.forEach((key) => {
344- argvPtrs.push(strPtr(`${key}=${this.env[key]}`));
345- });
346-
347- const argv = offset;
348- argvPtrs.forEach((ptr) => {
349- mem.setUint32(offset, ptr, true);
350- mem.setUint32(offset + 4, 0, true);
351- offset += 8;
352- });
353-
354- while (true) {
355- const callbackPromise = new Promise((resolve) => {
356- this._resolveCallbackPromise = () => {
357- if (this.exited) {
358- throw new Error("bad callback: Go program has already exited");
359- }
360- setTimeout(resolve, 0); // make sure it is asynchronous
361- };
362- });
363- this._inst.exports.run(argc, argv);
364- if (this.exited) {
365- break;
366- }
367- await callbackPromise;
368- }
369- }
370-
371- static _makeCallbackHelper(id, pendingCallbacks, go) {
372- return function() {
373- pendingCallbacks.push({ id: id, args: arguments });
374- go._resolveCallbackPromise();
375- };
376- }
377-
378- static _makeEventCallbackHelper(preventDefault, stopPropagation, stopImmediatePropagation, fn) {
379- return function(event) {
380- if (preventDefault) {
381- event.preventDefault();
382- }
383- if (stopPropagation) {
384- event.stopPropagation();
385- }
386- if (stopImmediatePropagation) {
387- event.stopImmediatePropagation();
388- }
389- fn(event);
390- };
391- }
392- }
393-};
6+ if (typeof global !== 'undefined') {
7+ // global already exists
8+ } else if (typeof window !== 'undefined') {
9+ window.global = window;
10+ } else if (typeof self !== 'undefined') {
11+ self.global = self;
12+ } else {
13+ throw new Error('cannot export Go (neither global, window nor self is defined)');
14+ }
15+
16+ // Map web browser API and Node.js API to a single common API (preferring web standards over Node.js API).
17+ let outputBuf = '';
18+ global.fs = {
19+ constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused
20+ writeSync(fd, buf) {
21+ outputBuf += decoder.decode(buf);
22+ const nl = outputBuf.lastIndexOf('\n');
23+ if (nl != -1) {
24+ console.log(outputBuf.substr(0, nl));
25+ outputBuf = outputBuf.substr(nl + 1);
26+ }
27+ return buf.length;
28+ },
29+ write(fd, buf, offset, length, position, callback) {
30+ if (offset !== 0 || length !== buf.length || position !== null) {
31+ throw new Error('not implemented');
32+ }
33+ const n = this.writeSync(fd, buf);
34+ callback(null, n);
35+ },
36+ open(path, flags, mode, callback) {
37+ const err = new Error('not implemented');
38+ err.code = 'ENOSYS';
39+ callback(err);
40+ },
41+ read(fd, buffer, offset, length, position, callback) {
42+ const err = new Error('not implemented');
43+ err.code = 'ENOSYS';
44+ callback(err);
45+ },
46+ fsync(fd, callback) {
47+ callback(null);
48+ },
49+ };
50+
51+ const encoder = new TextEncoder('utf-8');
52+ const decoder = new TextDecoder('utf-8');
53+
54+ global.Go = class {
55+ constructor() {
56+ this.argv = ['js'];
57+ this.env = {};
58+ this.exit = (code) => {
59+ if (code !== 0) {
60+ console.warn('exit code:', code);
61+ }
62+ };
63+ this._exitPromise = new Promise((resolve) => {
64+ this._resolveExitPromise = resolve;
65+ });
66+ this._pendingEvent = null;
67+ this._scheduledTimeouts = new Map();
68+ this._nextCallbackTimeoutID = 1;
69+
70+ const mem = () => {
71+ // The buffer may change when requesting more memory.
72+ return new DataView(this._inst.exports.mem.buffer);
73+ };
74+
75+ const setInt64 = (addr, v) => {
76+ mem().setUint32(addr + 0, v, true);
77+ mem().setUint32(addr + 4, Math.floor(v / 4294967296), true);
78+ };
79+
80+ const getInt64 = (addr) => {
81+ const low = mem().getUint32(addr + 0, true);
82+ const high = mem().getInt32(addr + 4, true);
83+ return low + high * 4294967296;
84+ };
85+
86+ const loadValue = (addr) => {
87+ const f = mem().getFloat64(addr, true);
88+ if (f === 0) {
89+ return undefined;
90+ }
91+ if (!isNaN(f)) {
92+ return f;
93+ }
94+
95+ const id = mem().getUint32(addr, true);
96+ return this._values[id];
97+ };
98+
99+ const storeValue = (addr, v) => {
100+ const nanHead = 0x7FF80000;
101+
102+ if (typeof v === 'number') {
103+ if (isNaN(v)) {
104+ mem().setUint32(addr + 4, nanHead, true);
105+ mem().setUint32(addr, 0, true);
106+ return;
107+ }
108+ if (v === 0) {
109+ mem().setUint32(addr + 4, nanHead, true);
110+ mem().setUint32(addr, 1, true);
111+ return;
112+ }
113+ mem().setFloat64(addr, v, true);
114+ return;
115+ }
116+
117+ switch (v) {
118+ case undefined:
119+ mem().setFloat64(addr, 0, true);
120+ return;
121+ case null:
122+ mem().setUint32(addr + 4, nanHead, true);
123+ mem().setUint32(addr, 2, true);
124+ return;
125+ case true:
126+ mem().setUint32(addr + 4, nanHead, true);
127+ mem().setUint32(addr, 3, true);
128+ return;
129+ case false:
130+ mem().setUint32(addr + 4, nanHead, true);
131+ mem().setUint32(addr, 4, true);
132+ return;
133+ }
134+
135+ let ref = this._refs.get(v);
136+ if (ref === undefined) {
137+ ref = this._values.length;
138+ this._values.push(v);
139+ this._refs.set(v, ref);
140+ }
141+ let typeFlag = 0;
142+ switch (typeof v) {
143+ case 'string':
144+ typeFlag = 1;
145+ break;
146+ case 'symbol':
147+ typeFlag = 2;
148+ break;
149+ case 'function':
150+ typeFlag = 3;
151+ break;
152+ }
153+ mem().setUint32(addr + 4, nanHead | typeFlag, true);
154+ mem().setUint32(addr, ref, true);
155+ };
156+
157+ const loadSlice = (addr) => {
158+ const array = getInt64(addr + 0);
159+ const len = getInt64(addr + 8);
160+ return new Uint8Array(this._inst.exports.mem.buffer, array, len);
161+ };
162+
163+ const loadSliceOfValues = (addr) => {
164+ const array = getInt64(addr + 0);
165+ const len = getInt64(addr + 8);
166+ const a = new Array(len);
167+ for (let i = 0; i < len; i++) {
168+ a[i] = loadValue(array + i * 8);
169+ }
170+ return a;
171+ };
172+
173+ const loadString = (addr) => {
174+ const saddr = getInt64(addr + 0);
175+ const len = getInt64(addr + 8);
176+ return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len));
177+ };
178+
179+ const timeOrigin = Date.now() - performance.now();
180+ this.importObject = {
181+ go: {
182+ // Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters)
183+ // may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported
184+ // function. A goroutine can switch to a new stack if the current stack is too small (see morestack function).
185+ // This changes the SP, thus we have to update the SP used by the imported function.
186+
187+ // func wasmExit(code int32)
188+ 'runtime.wasmExit': (sp) => {
189+ const code = mem().getInt32(sp + 8, true);
190+ this.exited = true;
191+ delete this._inst;
192+ delete this._values;
193+ delete this._refs;
194+ this.exit(code);
195+ },
196+
197+ // func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
198+ 'runtime.wasmWrite': (sp) => {
199+ const fd = getInt64(sp + 8);
200+ const p = getInt64(sp + 16);
201+ const n = mem().getInt32(sp + 24, true);
202+ fs.writeSync(fd, new Uint8Array(this._inst.exports.mem.buffer, p, n));
203+ },
204+
205+ // func nanotime() int64
206+ 'runtime.nanotime': (sp) => {
207+ setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000);
208+ },
209+
210+ // func walltime() (sec int64, nsec int32)
211+ 'runtime.walltime': (sp) => {
212+ const msec = (new Date).getTime();
213+ setInt64(sp + 8, msec / 1000);
214+ mem().setInt32(sp + 16, (msec % 1000) * 1000000, true);
215+ },
216+
217+ // func scheduleTimeoutEvent(delay int64) int32
218+ 'runtime.scheduleTimeoutEvent': (sp) => {
219+ const id = this._nextCallbackTimeoutID;
220+ this._nextCallbackTimeoutID++;
221+ this._scheduledTimeouts.set(id, setTimeout(
222+ () => { this._resume(); },
223+ getInt64(sp + 8) + 1, // setTimeout has been seen to fire up to 1 millisecond early
224+ ));
225+ mem().setInt32(sp + 16, id, true);
226+ },
227+
228+ // func clearTimeoutEvent(id int32)
229+ 'runtime.clearTimeoutEvent': (sp) => {
230+ const id = mem().getInt32(sp + 8, true);
231+ clearTimeout(this._scheduledTimeouts.get(id));
232+ this._scheduledTimeouts.delete(id);
233+ },
234+
235+ // func getRandomData(r []byte)
236+ 'runtime.getRandomData': (sp) => {
237+ crypto.getRandomValues(loadSlice(sp + 8));
238+ },
239+
240+ // func stringVal(value string) ref
241+ 'syscall/js.stringVal': (sp) => {
242+ storeValue(sp + 24, loadString(sp + 8));
243+ },
244+
245+ // func valueGet(v ref, p string) ref
246+ 'syscall/js.valueGet': (sp) => {
247+ const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16));
248+ sp = this._inst.exports.getsp(); // see comment above
249+ storeValue(sp + 32, result);
250+ },
251+
252+ // func valueSet(v ref, p string, x ref)
253+ 'syscall/js.valueSet': (sp) => {
254+ Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32));
255+ },
256+
257+ // func valueIndex(v ref, i int) ref
258+ 'syscall/js.valueIndex': (sp) => {
259+ storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16)));
260+ },
261+
262+ // valueSetIndex(v ref, i int, x ref)
263+ 'syscall/js.valueSetIndex': (sp) => {
264+ Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24));
265+ },
266+
267+ // func valueCall(v ref, m string, args []ref) (ref, bool)
268+ 'syscall/js.valueCall': (sp) => {
269+ try {
270+ const v = loadValue(sp + 8);
271+ const m = Reflect.get(v, loadString(sp + 16));
272+ const args = loadSliceOfValues(sp + 32);
273+ const result = Reflect.apply(m, v, args);
274+ sp = this._inst.exports.getsp(); // see comment above
275+ storeValue(sp + 56, result);
276+ mem().setUint8(sp + 64, 1);
277+ } catch (err) {
278+ storeValue(sp + 56, err);
279+ mem().setUint8(sp + 64, 0);
280+ }
281+ },
282+
283+ // func valueInvoke(v ref, args []ref) (ref, bool)
284+ 'syscall/js.valueInvoke': (sp) => {
285+ try {
286+ const v = loadValue(sp + 8);
287+ const args = loadSliceOfValues(sp + 16);
288+ const result = Reflect.apply(v, undefined, args);
289+ sp = this._inst.exports.getsp(); // see comment above
290+ storeValue(sp + 40, result);
291+ mem().setUint8(sp + 48, 1);
292+ } catch (err) {
293+ storeValue(sp + 40, err);
294+ mem().setUint8(sp + 48, 0);
295+ }
296+ },
297+
298+ // func valueNew(v ref, args []ref) (ref, bool)
299+ 'syscall/js.valueNew': (sp) => {
300+ try {
301+ const v = loadValue(sp + 8);
302+ const args = loadSliceOfValues(sp + 16);
303+ const result = Reflect.construct(v, args);
304+ sp = this._inst.exports.getsp(); // see comment above
305+ storeValue(sp + 40, result);
306+ mem().setUint8(sp + 48, 1);
307+ } catch (err) {
308+ storeValue(sp + 40, err);
309+ mem().setUint8(sp + 48, 0);
310+ }
311+ },
312+
313+ // func valueLength(v ref) int
314+ 'syscall/js.valueLength': (sp) => {
315+ setInt64(sp + 16, parseInt(loadValue(sp + 8).length));
316+ },
317+
318+ // valuePrepareString(v ref) (ref, int)
319+ 'syscall/js.valuePrepareString': (sp) => {
320+ const str = encoder.encode(String(loadValue(sp + 8)));
321+ storeValue(sp + 16, str);
322+ setInt64(sp + 24, str.length);
323+ },
324+
325+ // valueLoadString(v ref, b []byte)
326+ 'syscall/js.valueLoadString': (sp) => {
327+ const str = loadValue(sp + 8);
328+ loadSlice(sp + 16).set(str);
329+ },
330+
331+ // func valueInstanceOf(v ref, t ref) bool
332+ 'syscall/js.valueInstanceOf': (sp) => {
333+ mem().setUint8(sp + 24, loadValue(sp + 8) instanceof loadValue(sp + 16));
334+ },
335+
336+ 'debug': (value) => {
337+ console.log(value);
338+ },
339+ }
340+ };
341+ }
342+
343+ async run(instance) {
344+ this._inst = instance;
345+ this._values = [ // TODO: garbage collection
346+ NaN,
347+ 0,
348+ null,
349+ true,
350+ false,
351+ global,
352+ this._inst.exports.mem,
353+ this,
354+ ];
355+ this._refs = new Map();
356+ this.exited = false;
357+
358+ const mem = new DataView(this._inst.exports.mem.buffer);
359+
360+ // Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory.
361+ let offset = 4096;
362+
363+ const strPtr = (str) => {
364+ let ptr = offset;
365+ new Uint8Array(mem.buffer, offset, str.length + 1).set(encoder.encode(str + '\0'));
366+ offset += str.length + (8 - (str.length % 8));
367+ return ptr;
368+ };
369+
370+ const argc = this.argv.length;
371+
372+ const argvPtrs = [];
373+ this.argv.forEach((arg) => {
374+ argvPtrs.push(strPtr(arg));
375+ });
376+
377+ const keys = Object.keys(this.env).sort();
378+ argvPtrs.push(keys.length);
379+ keys.forEach((key) => {
380+ argvPtrs.push(strPtr(`${key}=${this.env[key]}`));
381+ });
382+
383+ const argv = offset;
384+ argvPtrs.forEach((ptr) => {
385+ mem.setUint32(offset, ptr, true);
386+ mem.setUint32(offset + 4, 0, true);
387+ offset += 8;
388+ });
389+
390+ this._inst.exports.run(argc, argv);
391+ if (this.exited) {
392+ this._resolveExitPromise();
393+ }
394+ await this._exitPromise;
395+ }
396+
397+ _resume() {
398+ if (this.exited) {
399+ throw new Error('Go program has already exited');
400+ }
401+ this._inst.exports.resume();
402+ if (this.exited) {
403+ this._resolveExitPromise();
404+ }
405+ }
406+
407+ _makeFuncWrapper(id) {
408+ const go = this;
409+ return function () {
410+ const event = { id: id, this: this, args: arguments };
411+ go._pendingEvent = event;
412+ go._resume();
413+ return event.result;
414+ };
415+ }
416+ };
417+}
Show on old repository browser