@parity/product-sdk-terminal 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -49
- package/dist/adapter-Dt3ryKnw.d.ts +72 -0
- package/dist/{chunk-5MCLSFKQ.js → chunk-GHOFKVUG.js} +1 -1
- package/dist/chunk-GHOFKVUG.js.map +1 -0
- package/dist/host.d.ts +113 -0
- package/dist/host.js +1405 -0
- package/dist/host.js.map +1 -0
- package/dist/index.d.ts +59 -62
- package/dist/index.js +192 -202
- package/dist/index.js.map +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +12 -4
- package/dist/testing.js.map +1 -1
- package/package.json +15 -18
- package/dist/chunk-5MCLSFKQ.js.map +0 -1
- package/dist/loader.mjs +0 -76
- package/dist/register.d.ts +0 -2
- package/dist/register.js +0 -9
- package/dist/register.js.map +0 -1
- package/scripts/patch-wasm.sh +0 -27
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createNodeStorageAdapter
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-GHOFKVUG.js";
|
|
4
4
|
|
|
5
5
|
// src/adapter.ts
|
|
6
6
|
import {
|
|
@@ -26,7 +26,6 @@ function createTerminalAdapter(options) {
|
|
|
26
26
|
const statementStore = createPapiStatementStoreAdapter(trackedLazyClient);
|
|
27
27
|
const adapter = createPappAdapter({
|
|
28
28
|
appId: options.appId,
|
|
29
|
-
metadata: options.metadataUrl,
|
|
30
29
|
hostMetadata: options.hostMetadata,
|
|
31
30
|
adapters: {
|
|
32
31
|
storage,
|
|
@@ -38,6 +37,7 @@ function createTerminalAdapter(options) {
|
|
|
38
37
|
return {
|
|
39
38
|
...adapter,
|
|
40
39
|
appId: options.appId,
|
|
40
|
+
storageDir: options.storageDir,
|
|
41
41
|
destroy() {
|
|
42
42
|
if (destroyPromise) return destroyPromise;
|
|
43
43
|
destroyPromise = teardown(adapter.sessions, trackedLazyClient);
|
|
@@ -272,71 +272,86 @@ if (void 0) {
|
|
|
272
272
|
var fakeLazyClient2;
|
|
273
273
|
|
|
274
274
|
// src/signer.ts
|
|
275
|
-
import {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
metadataHash: payload.metadataHash ? asHex(payload.metadataHash) : void 0,
|
|
301
|
-
mode: payload.mode,
|
|
302
|
-
withSignedTransaction: payload.withSignedTransaction
|
|
303
|
-
});
|
|
304
|
-
if (result.isErr()) {
|
|
305
|
-
throw new Error(`Mobile signing rejected: ${result.error.message}`);
|
|
275
|
+
import { decAnyMetadata, unifyMetadata } from "@polkadot-api/substrate-bindings";
|
|
276
|
+
function buildCreateTransactionRequest(productAccountId, callData, signedExtensions, txExtVersion) {
|
|
277
|
+
const checkGenesis = signedExtensions.CheckGenesis;
|
|
278
|
+
if (!checkGenesis) {
|
|
279
|
+
throw new Error(
|
|
280
|
+
"Cannot build transaction: chain did not provide the CheckGenesis signed extension"
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
payload: {
|
|
285
|
+
tag: "v1",
|
|
286
|
+
value: {
|
|
287
|
+
signer: productAccountId,
|
|
288
|
+
// CheckGenesis carries the genesis hash as its additionalSigned (implicit) data.
|
|
289
|
+
genesisHash: checkGenesis.additionalSigned,
|
|
290
|
+
callData,
|
|
291
|
+
extensions: Object.values(signedExtensions).map(
|
|
292
|
+
({ identifier, value, additionalSigned }) => ({
|
|
293
|
+
id: identifier,
|
|
294
|
+
extra: value,
|
|
295
|
+
additionalSigned
|
|
296
|
+
})
|
|
297
|
+
),
|
|
298
|
+
txExtVersion
|
|
299
|
+
}
|
|
306
300
|
}
|
|
307
|
-
return {
|
|
308
|
-
signature: toHex(result.value.signature),
|
|
309
|
-
signedTransaction: result.value.signedTransaction ? toHex(result.value.signedTransaction) : void 0
|
|
310
|
-
};
|
|
311
301
|
};
|
|
312
302
|
}
|
|
313
|
-
function
|
|
314
|
-
|
|
303
|
+
function txExtVersionFromMetadata(metadata) {
|
|
304
|
+
const decoded = unifyMetadata(decAnyMetadata(metadata));
|
|
305
|
+
const latestVersion = decoded.extrinsic.version.reduce((max, v) => Math.max(max, v), 0);
|
|
306
|
+
return latestVersion === 4 ? 0 : latestVersion;
|
|
307
|
+
}
|
|
308
|
+
async function requestSignedTransaction(session, request) {
|
|
309
|
+
const result = await session.createTransaction(request);
|
|
310
|
+
if (result.isErr()) {
|
|
311
|
+
throw new Error(`Mobile transaction signing rejected: ${result.error.message}`);
|
|
312
|
+
}
|
|
313
|
+
return result.value;
|
|
314
|
+
}
|
|
315
|
+
function makeTxSignTx(session, productAccountId) {
|
|
316
|
+
return async (callData, signedExtensions, metadata) => requestSignedTransaction(
|
|
317
|
+
session,
|
|
318
|
+
buildCreateTransactionRequest(
|
|
319
|
+
productAccountId,
|
|
320
|
+
callData,
|
|
321
|
+
signedExtensions,
|
|
322
|
+
txExtVersionFromMetadata(metadata)
|
|
323
|
+
)
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
function makeRawBytesSignCallback(session, productAccountId) {
|
|
327
|
+
return async (data) => {
|
|
315
328
|
const result = await session.signRaw({
|
|
316
329
|
productAccountId,
|
|
317
|
-
data: { tag: "Bytes", value:
|
|
330
|
+
data: { tag: "Bytes", value: data }
|
|
318
331
|
});
|
|
319
332
|
if (result.isErr()) {
|
|
320
333
|
throw new Error(`Mobile signing rejected: ${result.error.message}`);
|
|
321
334
|
}
|
|
322
|
-
return
|
|
323
|
-
id: 0,
|
|
324
|
-
signature: toHex(result.value.signature)
|
|
325
|
-
};
|
|
335
|
+
return result.value.signature;
|
|
326
336
|
};
|
|
327
337
|
}
|
|
328
338
|
function buildSessionSigner(session, ref) {
|
|
329
|
-
const accountId = new Uint8Array(session.remoteAccount.accountId);
|
|
330
339
|
const productAccountId = [ref.productId, ref.derivationIndex];
|
|
331
|
-
const
|
|
332
|
-
return
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
340
|
+
const publicKey = ref.publicKey ?? new Uint8Array(session.remoteAccount.accountId);
|
|
341
|
+
return {
|
|
342
|
+
publicKey,
|
|
343
|
+
// Transaction signing → host-papp `createTransaction`: the wallet builds
|
|
344
|
+
// and signs the extrinsic, so it can show a decoded tx (no `<Bytes>`
|
|
345
|
+
// envelope) and unknown signed extensions (e.g. `AsPgas`) survive.
|
|
346
|
+
signTx: makeTxSignTx(session, productAccountId),
|
|
347
|
+
// Arbitrary-byte signing keeps the `Bytes` tag so the wallet applies the
|
|
348
|
+
// `<Bytes>...</Bytes>` anti-phishing envelope exactly once on its side
|
|
349
|
+
// (correct for non-extrinsic user data).
|
|
350
|
+
signBytes: makeRawBytesSignCallback(session, productAccountId)
|
|
351
|
+
};
|
|
337
352
|
}
|
|
338
|
-
function createSessionSigner(session, adapter) {
|
|
339
|
-
return buildSessionSigner(session, { productId: adapter.appId, derivationIndex: 0 });
|
|
353
|
+
function createSessionSigner(session, adapter, publicKey) {
|
|
354
|
+
return buildSessionSigner(session, { productId: adapter.appId, derivationIndex: 0, publicKey });
|
|
340
355
|
}
|
|
341
356
|
function createSessionSignerForAccount(session, ref) {
|
|
342
357
|
return buildSessionSigner(session, ref);
|
|
@@ -355,16 +370,27 @@ if (void 0) {
|
|
|
355
370
|
opts.signRaw ?? (async () => {
|
|
356
371
|
throw new Error("signRaw not stubbed in this test");
|
|
357
372
|
})
|
|
373
|
+
),
|
|
374
|
+
createTransaction: vi.fn(
|
|
375
|
+
opts.createTransaction ?? (async () => {
|
|
376
|
+
throw new Error("createTransaction not stubbed in this test");
|
|
377
|
+
})
|
|
358
378
|
)
|
|
359
379
|
};
|
|
380
|
+
}, ext = function(identifier, value, additionalSigned) {
|
|
381
|
+
return {
|
|
382
|
+
identifier,
|
|
383
|
+
value: new Uint8Array(value),
|
|
384
|
+
additionalSigned: new Uint8Array(additionalSigned)
|
|
385
|
+
};
|
|
360
386
|
}, fakeAdapter = function(appId) {
|
|
361
387
|
return { appId };
|
|
362
388
|
};
|
|
363
|
-
makeSession2 = makeSession, fakeAdapter2 = fakeAdapter;
|
|
389
|
+
makeSession2 = makeSession, ext2 = ext, fakeAdapter2 = fakeAdapter;
|
|
364
390
|
const { describe, test, expect, vi } = void 0;
|
|
365
391
|
const { ok, err } = await null;
|
|
366
392
|
describe("createSessionSigner", () => {
|
|
367
|
-
test("
|
|
393
|
+
test("falls back to remoteAccount.accountId when no product key is passed", () => {
|
|
368
394
|
const bytes = Array.from({ length: 32 }, (_, i) => i);
|
|
369
395
|
const signer = createSessionSigner(
|
|
370
396
|
makeSession({ accountIdBytes: bytes }),
|
|
@@ -372,7 +398,18 @@ if (void 0) {
|
|
|
372
398
|
);
|
|
373
399
|
expect(signer.publicKey).toEqual(new Uint8Array(bytes));
|
|
374
400
|
});
|
|
375
|
-
test("
|
|
401
|
+
test("uses the host-supplied product-account public key when provided", () => {
|
|
402
|
+
const walletBytes = Array.from({ length: 32 }, (_, i) => i);
|
|
403
|
+
const productKey = new Uint8Array(32).fill(171);
|
|
404
|
+
const signer = createSessionSigner(
|
|
405
|
+
makeSession({ accountIdBytes: walletBytes }),
|
|
406
|
+
fakeAdapter("test-app"),
|
|
407
|
+
productKey
|
|
408
|
+
);
|
|
409
|
+
expect(signer.publicKey).toEqual(productKey);
|
|
410
|
+
expect(signer.publicKey).not.toEqual(new Uint8Array(walletBytes));
|
|
411
|
+
});
|
|
412
|
+
test("signBytes routes through session.signRaw with the Bytes tag", async () => {
|
|
376
413
|
const sig = new Uint8Array([9, 8, 7, 6, 5, 4, 3, 2, 1]);
|
|
377
414
|
const captured = [];
|
|
378
415
|
const session = makeSession({
|
|
@@ -388,9 +425,9 @@ if (void 0) {
|
|
|
388
425
|
const req = captured[0];
|
|
389
426
|
expect(req.productAccountId).toEqual(["test-app", 0]);
|
|
390
427
|
expect(req.data.tag).toBe("Bytes");
|
|
391
|
-
expect(req.data.value).
|
|
428
|
+
expect(req.data.value).toEqual(new Uint8Array([1, 2, 3]));
|
|
392
429
|
});
|
|
393
|
-
test("signBytes
|
|
430
|
+
test("signBytes never calls session.signPayload (legacy-path regression guard)", async () => {
|
|
394
431
|
const session = makeSession({
|
|
395
432
|
signRaw: async () => ok({ signature: new Uint8Array([1]) })
|
|
396
433
|
});
|
|
@@ -400,7 +437,7 @@ if (void 0) {
|
|
|
400
437
|
expect(sessionWithSpies.signPayload.mock.calls).toHaveLength(0);
|
|
401
438
|
expect(sessionWithSpies.signRaw.mock.calls).toHaveLength(1);
|
|
402
439
|
});
|
|
403
|
-
test("
|
|
440
|
+
test("signBytes throws with a clear error when the mobile rejects", async () => {
|
|
404
441
|
const session = makeSession({
|
|
405
442
|
signRaw: async () => err({ message: "user declined" })
|
|
406
443
|
});
|
|
@@ -410,148 +447,108 @@ if (void 0) {
|
|
|
410
447
|
);
|
|
411
448
|
});
|
|
412
449
|
});
|
|
413
|
-
describe("
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
450
|
+
describe("buildCreateTransactionRequest \u2014 tx payload (the AsPgas fix)", () => {
|
|
451
|
+
const checkGenesis = ext("CheckGenesis", [], [17, 34, 51]);
|
|
452
|
+
test("wraps the payload as v1 with signer, callData, and txExtVersion", () => {
|
|
453
|
+
const callData = new Uint8Array([202, 17]);
|
|
454
|
+
const req = buildCreateTransactionRequest(
|
|
455
|
+
["my-app", 3],
|
|
456
|
+
callData,
|
|
457
|
+
{ CheckGenesis: checkGenesis },
|
|
458
|
+
5
|
|
459
|
+
);
|
|
460
|
+
expect(req.payload.tag).toBe("v1");
|
|
461
|
+
expect(req.payload.value.signer).toEqual(["my-app", 3]);
|
|
462
|
+
expect(req.payload.value.callData).toEqual(callData);
|
|
463
|
+
expect(req.payload.value.txExtVersion).toBe(5);
|
|
464
|
+
});
|
|
465
|
+
test("takes the genesis hash from CheckGenesis.additionalSigned", () => {
|
|
466
|
+
const req = buildCreateTransactionRequest(
|
|
467
|
+
["my-app", 0],
|
|
468
|
+
new Uint8Array([0]),
|
|
469
|
+
{ CheckGenesis: checkGenesis },
|
|
470
|
+
0
|
|
471
|
+
);
|
|
472
|
+
expect(req.payload.value.genesisHash).toEqual(new Uint8Array([17, 34, 51]));
|
|
473
|
+
});
|
|
474
|
+
test("maps every signed extension to { id, extra, additionalSigned }", () => {
|
|
475
|
+
const req = buildCreateTransactionRequest(
|
|
476
|
+
["my-app", 0],
|
|
477
|
+
new Uint8Array([0]),
|
|
478
|
+
{ CheckGenesis: checkGenesis, CheckNonce: ext("CheckNonce", [7], []) },
|
|
479
|
+
0
|
|
480
|
+
);
|
|
481
|
+
expect(req.payload.value.extensions).toEqual([
|
|
482
|
+
{
|
|
483
|
+
id: "CheckGenesis",
|
|
484
|
+
extra: new Uint8Array([]),
|
|
485
|
+
additionalSigned: new Uint8Array([17, 34, 51])
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
id: "CheckNonce",
|
|
489
|
+
extra: new Uint8Array([7]),
|
|
490
|
+
additionalSigned: new Uint8Array([])
|
|
440
491
|
}
|
|
492
|
+
]);
|
|
493
|
+
});
|
|
494
|
+
test("preserves an unknown signed extension verbatim (e.g. AsPgas)", () => {
|
|
495
|
+
const req = buildCreateTransactionRequest(
|
|
496
|
+
["my-app", 0],
|
|
497
|
+
new Uint8Array([0]),
|
|
498
|
+
{ CheckGenesis: checkGenesis, AsPgas: ext("AsPgas", [222, 173], [190, 239]) },
|
|
499
|
+
0
|
|
500
|
+
);
|
|
501
|
+
expect(req.payload.value.extensions).toContainEqual({
|
|
502
|
+
id: "AsPgas",
|
|
503
|
+
extra: new Uint8Array([222, 173]),
|
|
504
|
+
additionalSigned: new Uint8Array([190, 239])
|
|
441
505
|
});
|
|
442
|
-
const callback = makeSignPayloadCallback(session, ["my-app", 0]);
|
|
443
|
-
await callback(pjsPayload());
|
|
444
|
-
expect(captured).toHaveLength(1);
|
|
445
|
-
const req = captured[0];
|
|
446
|
-
expect(req.productAccountId).toEqual(["my-app", 0]);
|
|
447
|
-
});
|
|
448
|
-
test("does NOT call session.signRaw (BadProof regression guard)", async () => {
|
|
449
|
-
const session = makeSession({
|
|
450
|
-
signPayload: async () => ok({ signature: new Uint8Array([1]), signedTransaction: void 0 })
|
|
451
|
-
});
|
|
452
|
-
const callback = makeSignPayloadCallback(session, ["my-app", 0]);
|
|
453
|
-
await callback(pjsPayload());
|
|
454
|
-
const sessionWithSpies = session;
|
|
455
|
-
expect(sessionWithSpies.signPayload.mock.calls).toHaveLength(1);
|
|
456
|
-
expect(sessionWithSpies.signRaw.mock.calls).toHaveLength(0);
|
|
457
506
|
});
|
|
458
|
-
test("
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
captured.push(req2);
|
|
463
|
-
return ok({
|
|
464
|
-
signature: new Uint8Array([0]),
|
|
465
|
-
signedTransaction: void 0
|
|
466
|
-
});
|
|
467
|
-
}
|
|
468
|
-
});
|
|
469
|
-
const callback = makeSignPayloadCallback(session, ["my-app", 0]);
|
|
470
|
-
await callback(
|
|
471
|
-
pjsPayload({
|
|
472
|
-
// Mix of already-prefixed and unprefixed inputs to exercise asHex.
|
|
473
|
-
blockHash: `0x${"ab".repeat(32)}`,
|
|
474
|
-
nonce: "1234abcd"
|
|
475
|
-
// unprefixed — asHex must add 0x
|
|
476
|
-
})
|
|
477
|
-
);
|
|
478
|
-
const req = captured[0];
|
|
479
|
-
for (const field of [
|
|
480
|
-
"blockHash",
|
|
481
|
-
"blockNumber",
|
|
482
|
-
"era",
|
|
483
|
-
"genesisHash",
|
|
484
|
-
"method",
|
|
485
|
-
"nonce",
|
|
486
|
-
"specVersion",
|
|
487
|
-
"tip",
|
|
488
|
-
"transactionVersion"
|
|
489
|
-
]) {
|
|
490
|
-
expect(req[field], `${field} must be 0x-prefixed`).toMatch(/^0x[0-9a-fA-F]*$/);
|
|
491
|
-
}
|
|
507
|
+
test("throws a clear error when CheckGenesis is absent", () => {
|
|
508
|
+
expect(
|
|
509
|
+
() => buildCreateTransactionRequest(["my-app", 0], new Uint8Array([0]), {}, 0)
|
|
510
|
+
).toThrow(/CheckGenesis/);
|
|
492
511
|
});
|
|
493
|
-
|
|
512
|
+
});
|
|
513
|
+
describe("requestSignedTransaction \u2014 SSO round-trip", () => {
|
|
514
|
+
const request = buildCreateTransactionRequest(
|
|
515
|
+
["my-app", 0],
|
|
516
|
+
new Uint8Array([0]),
|
|
517
|
+
{ CheckGenesis: ext("CheckGenesis", [], [1]) },
|
|
518
|
+
0
|
|
519
|
+
);
|
|
520
|
+
test("returns the signed extrinsic bytes from the mobile response", async () => {
|
|
521
|
+
const signed = new Uint8Array([171, 205, 239]);
|
|
522
|
+
const session = makeSession({ createTransaction: async () => ok(signed) });
|
|
523
|
+
const out = await requestSignedTransaction(session, request);
|
|
524
|
+
expect(out).toBe(signed);
|
|
525
|
+
});
|
|
526
|
+
test("calls session.createTransaction \u2014 never signRaw/signPayload \u2014 with the request", async () => {
|
|
494
527
|
const captured = [];
|
|
495
528
|
const session = makeSession({
|
|
496
|
-
|
|
497
|
-
captured.push(
|
|
498
|
-
return ok(
|
|
499
|
-
signature: new Uint8Array([0]),
|
|
500
|
-
signedTransaction: void 0
|
|
501
|
-
});
|
|
529
|
+
createTransaction: async (req) => {
|
|
530
|
+
captured.push(req);
|
|
531
|
+
return ok(new Uint8Array([1]));
|
|
502
532
|
}
|
|
503
533
|
});
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
assetId: "0xfeed"
|
|
511
|
-
})
|
|
512
|
-
);
|
|
513
|
-
const req = captured[0];
|
|
514
|
-
expect(req.metadataHash).toBe("0xdeadbeef");
|
|
515
|
-
expect(req.mode).toBe(1);
|
|
516
|
-
expect(req.withSignedTransaction).toBe(true);
|
|
517
|
-
expect(req.assetId).toBe("0xfeed");
|
|
518
|
-
});
|
|
519
|
-
test("hex-encodes signature and signedTransaction in the PJS return shape", async () => {
|
|
520
|
-
const session = makeSession({
|
|
521
|
-
signPayload: async () => ok({
|
|
522
|
-
signature: new Uint8Array([171, 205]),
|
|
523
|
-
signedTransaction: new Uint8Array([1, 2, 3])
|
|
524
|
-
})
|
|
525
|
-
});
|
|
526
|
-
const callback = makeSignPayloadCallback(session, ["my-app", 0]);
|
|
527
|
-
const result = await callback(pjsPayload());
|
|
528
|
-
expect(result.signature).toBe("0xabcd");
|
|
529
|
-
expect(result.signedTransaction).toBe("0x010203");
|
|
530
|
-
});
|
|
531
|
-
test("omits signedTransaction when host-papp returns undefined", async () => {
|
|
532
|
-
const session = makeSession({
|
|
533
|
-
signPayload: async () => ok({
|
|
534
|
-
signature: new Uint8Array([0]),
|
|
535
|
-
signedTransaction: void 0
|
|
536
|
-
})
|
|
537
|
-
});
|
|
538
|
-
const callback = makeSignPayloadCallback(session, ["my-app", 0]);
|
|
539
|
-
const result = await callback(pjsPayload());
|
|
540
|
-
expect(result.signature).toBe("0x00");
|
|
541
|
-
expect(result.signedTransaction).toBeUndefined();
|
|
534
|
+
await requestSignedTransaction(session, request);
|
|
535
|
+
expect(captured).toEqual([request]);
|
|
536
|
+
const spies = session;
|
|
537
|
+
expect(spies.createTransaction.mock.calls).toHaveLength(1);
|
|
538
|
+
expect(spies.signPayload.mock.calls).toHaveLength(0);
|
|
539
|
+
expect(spies.signRaw.mock.calls).toHaveLength(0);
|
|
542
540
|
});
|
|
543
541
|
test("throws a clear error when the mobile rejects", async () => {
|
|
544
542
|
const session = makeSession({
|
|
545
|
-
|
|
543
|
+
createTransaction: async () => err({ message: "user declined" })
|
|
546
544
|
});
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
"Mobile signing rejected: user declined"
|
|
545
|
+
await expect(requestSignedTransaction(session, request)).rejects.toThrow(
|
|
546
|
+
"Mobile transaction signing rejected: user declined"
|
|
550
547
|
);
|
|
551
548
|
});
|
|
552
549
|
});
|
|
553
|
-
describe("
|
|
554
|
-
test("forwards
|
|
550
|
+
describe("makeRawBytesSignCallback", () => {
|
|
551
|
+
test("forwards data verbatim under the Bytes tag with the right productAccountId", async () => {
|
|
555
552
|
const captured = [];
|
|
556
553
|
const session = makeSession({
|
|
557
554
|
signRaw: async (req2) => {
|
|
@@ -559,30 +556,22 @@ if (void 0) {
|
|
|
559
556
|
return ok({ signature: new Uint8Array([255]) });
|
|
560
557
|
}
|
|
561
558
|
});
|
|
562
|
-
const callback =
|
|
563
|
-
await callback(
|
|
564
|
-
address: `0x${"00".repeat(32)}`,
|
|
565
|
-
data: "0xdeadbeef",
|
|
566
|
-
type: "bytes"
|
|
567
|
-
});
|
|
559
|
+
const callback = makeRawBytesSignCallback(session, ["my-app", 5]);
|
|
560
|
+
await callback(new Uint8Array([222, 173, 190, 239]));
|
|
568
561
|
expect(captured).toHaveLength(1);
|
|
569
562
|
const req = captured[0];
|
|
570
563
|
expect(req.productAccountId).toEqual(["my-app", 5]);
|
|
571
564
|
expect(req.data.tag).toBe("Bytes");
|
|
572
565
|
expect(Array.from(req.data.value)).toEqual([222, 173, 190, 239]);
|
|
573
566
|
});
|
|
574
|
-
test("
|
|
567
|
+
test("returns the raw signature bytes from the mobile response", async () => {
|
|
568
|
+
const sig = new Uint8Array([66]);
|
|
575
569
|
const session = makeSession({
|
|
576
|
-
signRaw: async () => ok({ signature:
|
|
577
|
-
});
|
|
578
|
-
const callback = makeSignRawCallback(session, ["my-app", 0]);
|
|
579
|
-
const result = await callback({
|
|
580
|
-
address: `0x${"00".repeat(32)}`,
|
|
581
|
-
data: "0x00",
|
|
582
|
-
type: "bytes"
|
|
570
|
+
signRaw: async () => ok({ signature: sig })
|
|
583
571
|
});
|
|
584
|
-
|
|
585
|
-
|
|
572
|
+
const callback = makeRawBytesSignCallback(session, ["my-app", 0]);
|
|
573
|
+
const out = await callback(new Uint8Array([0]));
|
|
574
|
+
expect(out).toBe(sig);
|
|
586
575
|
});
|
|
587
576
|
});
|
|
588
577
|
describe("createSessionSignerForAccount", () => {
|
|
@@ -624,6 +613,7 @@ if (void 0) {
|
|
|
624
613
|
});
|
|
625
614
|
}
|
|
626
615
|
var makeSession2;
|
|
616
|
+
var ext2;
|
|
627
617
|
var fakeAdapter2;
|
|
628
618
|
|
|
629
619
|
// src/sessions.ts
|