Skip to content

Commit 801f166

Browse files
committed
wip: feat(simf): spend, pt.5
1 parent 4984eab commit 801f166

File tree

7 files changed

+113
-55
lines changed

7 files changed

+113
-55
lines changed

Justfile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,14 @@ wasm-sh:
1010
# Compile dev builds of all WASM modules.
1111
wasm:
1212
time just wasm-img
13+
time just wasm-simf
14+
time just wasm-namada
15+
# Compile dev builds of SimplicityHL module.
16+
wasm-simf:
1317
time docker run -v .:/app:rw --workdir=/app -it hackbg/fadroma:dev sh -c \
1418
"cd lib/platform/simf && just wasm"
19+
# Compile dev builds of Namada module.
20+
wasm-namada:
1521
time docker run -v .:/app:rw --workdir=/app -it hackbg/fadroma:dev sh -c \
1622
"cd lib/platform/namada && just wasm"
1723
# Report line counts.

lib/platform/btc.test.ts

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,11 @@
11
#!/usr/bin/env -S deno run --allow-env --allow-read --allow-run --allow-write=/tmp/fadroma --allow-import=cdn.skypack.dev:443,deno.land:443 --allow-net=127.0.0.1
2-
import { Fn, Test } from '../index.ts';
2+
import { Test } from '../index.ts';
33
import { Btc } from './btc.ts';
44
const { the, is, has } = Test;
5-
export const testBtcNode = the('Node', Btc,
6-
(btc: Btc) => btc.kill());
5+
export const testBtcNode = the('Node', Btc, (btc: Btc) => btc.kill());
76
export const testBtcOps = the('Ops',
87
the('Send', 'OP_CHECKSIG'),
98
the('Subscribe', 'TX', 'Block'),
109
the('Query', 'Block', 'Transaction', 'Address'));
1110
export default Test.suite(import.meta, 'Btc',
1211
testBtcNode, testBtcOps);
13-
14-
function cleanup (_, ctx: Test.Testing & { localnet?: { kill?: Fn } }) {
15-
if (ctx.localnet?.kill) ctx.localnet.kill()
16-
}
17-
18-
function calledWithMock (fn) {
19-
return fn(mockContext());
20-
}
21-
22-
function mockContext () {
23-
const mock = [];
24-
return {
25-
mock,
26-
exec (...args) { mock.push(args); return {} },
27-
spawn (...args) { mock.push(args); return {} },
28-
}
29-
}

lib/platform/btc.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,18 +101,28 @@ export namespace Btc {
101101
}
102102

103103
export interface Rest {
104+
tx: Fn,
104105
chaininfo: Fn,
105106
getutxos: Fn,
106107
}
107108

108109
/** Bitcoin node's optional REST API. */
109110
export const Rest = function btcRest (url: string): Rest {
110111
return {
111-
async chaininfo () {
112-
return JSON.parse(await callUrl(`${url}/rest/chaininfo.json`))
112+
async chaininfo (format = "json") {
113+
let data = await callUrl(`${url}/rest/chaininfo.${format}`);
114+
if (format === 'json') data = JSON.parse(data);
115+
return data;
113116
},
114-
async getutxos (...args: string[]) {
115-
return JSON.parse(await callUrl(`${url}/rest/getutxos/${args.join('/')}.json`))
117+
async tx (hash, format = "json") {
118+
let data = await callUrl(`${url}/rest/tx/${hash}.${format}`);
119+
if (format === 'json') data = JSON.parse(data);
120+
return data;
121+
},
122+
async getutxos (format = 'json', ...args: string[]) {
123+
let data = await callUrl(`${url}/rest/getutxos/${args.join('/')}.${format}`);
124+
if (format === 'json') data = JSON.parse(data);
125+
return data;
116126
},
117127
}
118128
}

lib/platform/simf.test.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,28 +88,31 @@ export default Test.suite(import.meta, 'Simf',
8888
));
8989

9090
function Withdraw (source, cb?) {
91-
return Name('Withdraw', async ({ rpc, rest }, { log }) => {
91+
return Name('Withdraw', async ({ rpc, rest, txId }, { log }) => {
92+
const destination = await rpc.getnewaddress();
93+
const tx = await rest.tx(txId);
9294
const program = await Simf(source).compile();
9395
log(program);
9496
const spend = program.spend({
95-
witness: '',
96-
destination: '',
97-
txId: '',
98-
txBytes: '',
97+
witness: '',
98+
destination,
99+
txId,
100+
txBytes: tx.hex,
99101
});
100102
log(spend);
101103
})
102104
}
103105

104106
function Deploy (p2tr, cb) {
105-
return Name(`Deploy ${p2tr}`, async (ctx: { rpc, rest }) => {
107+
return Name(`Deploy ${p2tr}`, async (ctx: { rpc, rest }, { log }) => {
106108
const address = await ctx.rpc.getnewaddress();
107109
equal((await ctx.rpc.validateaddress(address)).isvalid, true);
108-
const txid = await ctx.rpc.sendtoaddress(p2tr, 1000);
110+
const txId = await ctx.rpc.sendtoaddress(p2tr, 1000);
111+
log({ address, txId });
109112
await ctx.rpc.generatetoaddress(1, address);
110-
const { chainHeight, utxos } = await ctx.rest.getutxos(`${txid}-0/${txid}-1`);
113+
const { chainHeight, utxos } = await ctx.rest.getutxos('json', `${txId}-0/${txId}-1`);
111114
await cb({ chainHeight, utxos });
112-
return ctx;
115+
return Object.assign(ctx, { address, txId, chainHeight, utxos });
113116
})
114117
}
115118

lib/platform/simf/pkg/fadroma_simf.js

Lines changed: 74 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import * as __wbg_star0 from 'env';
2+
13
let wasm;
24

35
function addToExternrefTable0(obj) {
@@ -6,6 +8,16 @@ function addToExternrefTable0(obj) {
68
return idx;
79
}
810

11+
function _assertBoolean(n) {
12+
if (typeof(n) !== 'boolean') {
13+
throw new Error(`expected a boolean argument, found ${typeof(n)}`);
14+
}
15+
}
16+
17+
function _assertNum(n) {
18+
if (typeof(n) !== 'number') throw new Error(`expected a number argument, found ${typeof(n)}`);
19+
}
20+
921
function debugString(val) {
1022
// primitive types
1123
const type = typeof val;
@@ -110,7 +122,24 @@ function isLikeNone(x) {
110122
return x === undefined || x === null;
111123
}
112124

125+
function logError(f, args) {
126+
try {
127+
return f.apply(this, args);
128+
} catch (e) {
129+
let error = (function () {
130+
try {
131+
return e instanceof Error ? `${e.message}\n\nStack:\n${e.stack}` : e.toString();
132+
} catch(_) {
133+
return "<failed to stringify thrown value>";
134+
}
135+
}());
136+
console.error("wasm-bindgen: imported JS function that was not marked as `catch` threw an error:", error);
137+
throw e;
138+
}
139+
}
140+
113141
function passStringToWasm0(arg, malloc, realloc) {
142+
if (typeof(arg) !== 'string') throw new Error(`expected a string argument, found ${typeof(arg)}`);
114143
if (realloc === undefined) {
115144
const buf = cachedTextEncoder.encode(arg);
116145
const ptr = malloc(buf.length, 1) >>> 0;
@@ -138,7 +167,7 @@ function passStringToWasm0(arg, malloc, realloc) {
138167
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
139168
const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
140169
const ret = cachedTextEncoder.encodeInto(arg, view);
141-
170+
if (ret.read !== arg.length) throw new Error('failed to pass whole string');
142171
offset += ret.written;
143172
ptr = realloc(ptr, len, offset, 1) >>> 0;
144173
}
@@ -187,9 +216,12 @@ const ProgramFinalization = (typeof FinalizationRegistry === 'undefined')
187216
: new FinalizationRegistry(ptr => wasm.__wbg_program_free(ptr >>> 0, 1));
188217

189218
/**
190-
* Represents a valid and compiled SimplicityHL program.
219+
* A valid compiled SimplicityHL program.
191220
*/
192221
export class Program {
222+
constructor() {
223+
throw new Error('cannot invoke `new` directly');
224+
}
193225
static __wrap(ptr) {
194226
ptr = ptr >>> 0;
195227
const obj = Object.create(Program.prototype);
@@ -219,6 +251,8 @@ export class Program {
219251
* @returns {object}
220252
*/
221253
spend(options) {
254+
if (this.__wbg_ptr == 0) throw new Error('Attempt to use a moved value');
255+
_assertNum(this.__wbg_ptr);
222256
const ret = wasm.program_spend(this.__wbg_ptr, options);
223257
if (ret[2]) {
224258
throw takeFromExternrefTable0(ret[1]);
@@ -229,6 +263,8 @@ export class Program {
229263
* @returns {object}
230264
*/
231265
toJSON() {
266+
if (this.__wbg_ptr == 0) throw new Error('Attempt to use a moved value');
267+
_assertNum(this.__wbg_ptr);
232268
const ret = wasm.program_toJSON(this.__wbg_ptr);
233269
return ret;
234270
}
@@ -241,6 +277,8 @@ export class Program {
241277
let deferred1_0;
242278
let deferred1_1;
243279
try {
280+
if (this.__wbg_ptr == 0) throw new Error('Attempt to use a moved value');
281+
_assertNum(this.__wbg_ptr);
244282
const ret = wasm.program_toString(this.__wbg_ptr);
245283
deferred1_0 = ret[0];
246284
deferred1_1 = ret[1];
@@ -315,10 +353,10 @@ async function __wbg_load(module, imports) {
315353
function __wbg_get_imports() {
316354
const imports = {};
317355
imports.wbg = {};
318-
imports.wbg.__wbg_Error_52673b7de5a0ca89 = function(arg0, arg1) {
356+
imports.wbg.__wbg_Error_52673b7de5a0ca89 = function() { return logError(function (arg0, arg1) {
319357
const ret = Error(getStringFromWasm0(arg0, arg1));
320358
return ret;
321-
};
359+
}, arguments) };
322360
imports.wbg.__wbg___wbindgen_debug_string_adfb662ae34724b6 = function(arg0, arg1) {
323361
const ret = debugString(arg1);
324362
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
@@ -328,15 +366,18 @@ function __wbg_get_imports() {
328366
};
329367
imports.wbg.__wbg___wbindgen_is_falsy_7b9692021c137978 = function(arg0) {
330368
const ret = !arg0;
369+
_assertBoolean(ret);
331370
return ret;
332371
};
333372
imports.wbg.__wbg___wbindgen_is_object_ce774f3490692386 = function(arg0) {
334373
const val = arg0;
335374
const ret = typeof(val) === 'object' && val !== null;
375+
_assertBoolean(ret);
336376
return ret;
337377
};
338378
imports.wbg.__wbg___wbindgen_is_string_704ef9c8fc131030 = function(arg0) {
339379
const ret = typeof(arg0) === 'string';
380+
_assertBoolean(ret);
340381
return ret;
341382
};
342383
imports.wbg.__wbg___wbindgen_string_get_a2a31e16edf96e42 = function(arg0, arg1) {
@@ -350,7 +391,7 @@ function __wbg_get_imports() {
350391
imports.wbg.__wbg___wbindgen_throw_dd24417ed36fc46e = function(arg0, arg1) {
351392
throw new Error(getStringFromWasm0(arg0, arg1));
352393
};
353-
imports.wbg.__wbg_error_7534b8e9a36f1ab4 = function(arg0, arg1) {
394+
imports.wbg.__wbg_error_7534b8e9a36f1ab4 = function() { return logError(function (arg0, arg1) {
354395
let deferred0_0;
355396
let deferred0_1;
356397
try {
@@ -360,56 +401,68 @@ function __wbg_get_imports() {
360401
} finally {
361402
wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
362403
}
363-
};
404+
}, arguments) };
364405
imports.wbg.__wbg_get_af9dab7e9603ea93 = function() { return handleError(function (arg0, arg1) {
365406
const ret = Reflect.get(arg0, arg1);
366407
return ret;
367408
}, arguments) };
368-
imports.wbg.__wbg_instanceof_Uint8Array_da54ccc9d3e09434 = function(arg0) {
409+
imports.wbg.__wbg_instanceof_Uint8Array_da54ccc9d3e09434 = function() { return logError(function (arg0) {
369410
let result;
370411
try {
371412
result = arg0 instanceof Uint8Array;
372413
} catch (_) {
373414
result = false;
374415
}
375416
const ret = result;
417+
_assertBoolean(ret);
376418
return ret;
377-
};
378-
imports.wbg.__wbg_length_22ac23eaec9d8053 = function(arg0) {
419+
}, arguments) };
420+
imports.wbg.__wbg_length_22ac23eaec9d8053 = function() { return logError(function (arg0) {
379421
const ret = arg0.length;
422+
_assertNum(ret);
380423
return ret;
381-
};
382-
imports.wbg.__wbg_new_1ba21ce319a06297 = function() {
424+
}, arguments) };
425+
imports.wbg.__wbg_new_1ba21ce319a06297 = function() { return logError(function () {
383426
const ret = new Object();
384427
return ret;
385-
};
386-
imports.wbg.__wbg_new_8a6f238a6ece86ea = function() {
428+
}, arguments) };
429+
imports.wbg.__wbg_new_25f239778d6112b9 = function() { return logError(function () {
430+
const ret = new Array();
431+
return ret;
432+
}, arguments) };
433+
imports.wbg.__wbg_new_8a6f238a6ece86ea = function() { return logError(function () {
387434
const ret = new Error();
388435
return ret;
389-
};
390-
imports.wbg.__wbg_prototypesetcall_dfe9b766cdc1f1fd = function(arg0, arg1, arg2) {
436+
}, arguments) };
437+
imports.wbg.__wbg_prototypesetcall_dfe9b766cdc1f1fd = function() { return logError(function (arg0, arg1, arg2) {
391438
Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), arg2);
392-
};
439+
}, arguments) };
393440
imports.wbg.__wbg_set_781438a03c0c3c81 = function() { return handleError(function (arg0, arg1, arg2) {
394441
const ret = Reflect.set(arg0, arg1, arg2);
442+
_assertBoolean(ret);
395443
return ret;
396444
}, arguments) };
397-
imports.wbg.__wbg_stack_0ed75d68575b0f3c = function(arg0, arg1) {
445+
imports.wbg.__wbg_stack_0ed75d68575b0f3c = function() { return logError(function (arg0, arg1) {
398446
const ret = arg1.stack;
399447
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
400448
const len1 = WASM_VECTOR_LEN;
401449
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
402450
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
403-
};
451+
}, arguments) };
404452
imports.wbg.__wbg_stringify_655a6390e1f5eb6b = function() { return handleError(function (arg0) {
405453
const ret = JSON.stringify(arg0);
406454
return ret;
407455
}, arguments) };
408-
imports.wbg.__wbindgen_cast_2241b6af4c4b2941 = function(arg0, arg1) {
456+
imports.wbg.__wbindgen_cast_2241b6af4c4b2941 = function() { return logError(function (arg0, arg1) {
409457
// Cast intrinsic for `Ref(String) -> Externref`.
410458
const ret = getStringFromWasm0(arg0, arg1);
411459
return ret;
412-
};
460+
}, arguments) };
461+
imports.wbg.__wbindgen_cast_d6cd19b81560fd6e = function() { return logError(function (arg0) {
462+
// Cast intrinsic for `F64 -> Externref`.
463+
const ret = arg0;
464+
return ret;
465+
}, arguments) };
413466
imports.wbg.__wbindgen_init_externref_table = function() {
414467
const table = wasm.__wbindgen_externrefs;
415468
const offset = table.grow(4);
@@ -419,6 +472,7 @@ function __wbg_get_imports() {
419472
table.set(offset + 2, true);
420473
table.set(offset + 3, false);
421474
};
475+
imports['env'] = __wbg_star0;
422476

423477
return imports;
424478
}
2.16 MB
Binary file not shown.

lib/platform/simf/src/simf.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ impl Program {
111111
}
112112

113113
#[wasm_bindgen] pub fn spend (&self, options: Object) -> Maybe<Object> {
114+
console_error_panic_hook::set_once();
114115
if !options.is_object() {
115116
return Err(JsError::new("missing options object"))
116117
}
@@ -204,8 +205,10 @@ fn parse_addr (x: JsValue) -> Maybe<Address> {
204205
Ok(address)
205206
}
206207

207-
fn parse_tx_id (bytes: JsValue) -> Maybe<Txid> {
208-
unimplemented!()
208+
fn parse_tx_id (x: JsValue) -> Maybe<Txid> {
209+
let txid = required!("txid: not string": x.as_string())?;
210+
let txid = expected!("txid: not parsed": Txid::from_str(&txid))?;
211+
Ok(txid)
209212
}
210213

211214
fn parse_tx_bytes (bytes: JsValue) -> Maybe<Transaction> {

0 commit comments

Comments
 (0)