@icp-sdk/signer 5.2.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/LICENSE +190 -0
- package/README.md +165 -0
- package/lib/esm/agent/agent.d.ts +112 -0
- package/lib/esm/agent/agent.js +288 -0
- package/lib/esm/agent/agent.js.map +1 -0
- package/lib/esm/agent/index.d.ts +1 -0
- package/lib/esm/agent/index.js +2 -0
- package/lib/esm/agent/index.js.map +1 -0
- package/lib/esm/extension/browserExtensionChannel.d.ts +37 -0
- package/lib/esm/extension/browserExtensionChannel.js +80 -0
- package/lib/esm/extension/browserExtensionChannel.js.map +1 -0
- package/lib/esm/extension/browserExtensionTransport.d.ts +67 -0
- package/lib/esm/extension/browserExtensionTransport.js +70 -0
- package/lib/esm/extension/browserExtensionTransport.js.map +1 -0
- package/lib/esm/extension/index.d.ts +3 -0
- package/lib/esm/extension/index.js +3 -0
- package/lib/esm/extension/index.js.map +1 -0
- package/lib/esm/extension/types.d.ts +32 -0
- package/lib/esm/extension/types.js +2 -0
- package/lib/esm/extension/types.js.map +1 -0
- package/lib/esm/index.d.ts +2 -0
- package/lib/esm/index.js +2 -0
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/signer.d.ts +180 -0
- package/lib/esm/signer.js +427 -0
- package/lib/esm/signer.js.map +1 -0
- package/lib/esm/transport.d.ts +32 -0
- package/lib/esm/transport.js +11 -0
- package/lib/esm/transport.js.map +1 -0
- package/lib/esm/web/heartbeat/client.d.ts +60 -0
- package/lib/esm/web/heartbeat/client.js +112 -0
- package/lib/esm/web/heartbeat/client.js.map +1 -0
- package/lib/esm/web/heartbeat/server.d.ts +43 -0
- package/lib/esm/web/heartbeat/server.js +82 -0
- package/lib/esm/web/heartbeat/server.js.map +1 -0
- package/lib/esm/web/index.d.ts +4 -0
- package/lib/esm/web/index.js +5 -0
- package/lib/esm/web/index.js.map +1 -0
- package/lib/esm/web/postMessageChannel.d.ts +55 -0
- package/lib/esm/web/postMessageChannel.js +109 -0
- package/lib/esm/web/postMessageChannel.js.map +1 -0
- package/lib/esm/web/postMessageTransport.d.ts +96 -0
- package/lib/esm/web/postMessageTransport.js +113 -0
- package/lib/esm/web/postMessageTransport.js.map +1 -0
- package/package.json +122 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { HeartbeatClient } from './heartbeat/client.js';
|
|
2
|
+
import { PostMessageChannel } from './postMessageChannel.js';
|
|
3
|
+
const NON_CLICK_ESTABLISHMENT_LINK = 'https://github.com/slide-computer/signer-js/blob/main/packages/signer-web/README.md#channels-must-be-established-in-a-click-handler';
|
|
4
|
+
/** Error thrown by {@link PostMessageTransport} for transport-level failures. */
|
|
5
|
+
export class PostMessageTransportError extends Error {
|
|
6
|
+
}
|
|
7
|
+
// Tracks whether we're inside a click event handler.
|
|
8
|
+
// Capture phase sets true, bubble phase resets to false.
|
|
9
|
+
let withinClick = false;
|
|
10
|
+
if (globalThis.window) {
|
|
11
|
+
globalThis.window.addEventListener('click', () => (withinClick = true), true);
|
|
12
|
+
globalThis.window.addEventListener('click', () => (withinClick = false));
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* ICRC-29 post message transport for communicating with web-based signers.
|
|
16
|
+
*
|
|
17
|
+
* Opens a window to the signer's URL and establishes a communication channel
|
|
18
|
+
* using the ICRC-29 heartbeat protocol (`icrc29_status` polling). Messages
|
|
19
|
+
* are exchanged via `window.postMessage`.
|
|
20
|
+
* @see https://github.com/dfinity/wg-identity-authentication/blob/main/topics/icrc_29_window_post_message_transport.md
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* const transport = new PostMessageTransport({ url: "https://oisy.com/sign" });
|
|
24
|
+
* const signer = new Signer({ transport });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export class PostMessageTransport {
|
|
28
|
+
#options;
|
|
29
|
+
constructor(options) {
|
|
30
|
+
const isSecureContext = (() => {
|
|
31
|
+
try {
|
|
32
|
+
const url = new URL(options.url);
|
|
33
|
+
return (url.protocol === 'https:' ||
|
|
34
|
+
url.hostname === '127.0.0.1' ||
|
|
35
|
+
url.hostname.split('.').slice(-1)[0] === 'localhost');
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
})();
|
|
41
|
+
if (!isSecureContext) {
|
|
42
|
+
throw new PostMessageTransportError('Invalid signer RPC url');
|
|
43
|
+
}
|
|
44
|
+
this.#options = {
|
|
45
|
+
windowOpenerFeatures: '',
|
|
46
|
+
window: globalThis.window,
|
|
47
|
+
establishTimeout: 120000,
|
|
48
|
+
pendingTimeout: 300000,
|
|
49
|
+
disconnectTimeout: 2000,
|
|
50
|
+
statusPollingRate: 300,
|
|
51
|
+
crypto: globalThis.crypto,
|
|
52
|
+
manageFocus: true,
|
|
53
|
+
closeOnEstablishTimeout: true,
|
|
54
|
+
closeOnPendingTimeout: true,
|
|
55
|
+
detectNonClickEstablishment: true,
|
|
56
|
+
...options,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Opens the signer window and establishes a communication channel
|
|
61
|
+
* via the ICRC-29 heartbeat handshake.
|
|
62
|
+
* @throws {PostMessageTransportError} If called outside a click handler
|
|
63
|
+
* (when `detectNonClickEstablishment` is enabled), if the window
|
|
64
|
+
* cannot be opened, or if the handshake times out.
|
|
65
|
+
*/
|
|
66
|
+
establishChannel() {
|
|
67
|
+
if (this.#options.detectNonClickEstablishment && !withinClick) {
|
|
68
|
+
return Promise.reject(new PostMessageTransportError(`Signer window should not be opened outside of click handler, see: ${NON_CLICK_ESTABLISHMENT_LINK}`));
|
|
69
|
+
}
|
|
70
|
+
let signerWindow;
|
|
71
|
+
try {
|
|
72
|
+
const result = this.#options.window.open(this.#options.url, `${new URL(this.#options.url).origin}-signer-window`, this.#options.windowOpenerFeatures);
|
|
73
|
+
if (!result) {
|
|
74
|
+
return Promise.reject(new PostMessageTransportError('Signer window could not be opened'));
|
|
75
|
+
}
|
|
76
|
+
signerWindow = result;
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
return Promise.reject(new PostMessageTransportError(error instanceof Error ? error.message : 'Signer window could not be opened'));
|
|
80
|
+
}
|
|
81
|
+
return new Promise((resolve, reject) => {
|
|
82
|
+
let channel;
|
|
83
|
+
new HeartbeatClient({
|
|
84
|
+
...this.#options,
|
|
85
|
+
signerWindow,
|
|
86
|
+
onEstablish: (origin, status) => {
|
|
87
|
+
channel = new PostMessageChannel({
|
|
88
|
+
...this.#options,
|
|
89
|
+
signerOrigin: origin,
|
|
90
|
+
signerWindow,
|
|
91
|
+
signerStatus: status,
|
|
92
|
+
});
|
|
93
|
+
resolve(channel);
|
|
94
|
+
},
|
|
95
|
+
onEstablishTimeout: () => {
|
|
96
|
+
if (this.#options.closeOnEstablishTimeout) {
|
|
97
|
+
signerWindow.close();
|
|
98
|
+
}
|
|
99
|
+
reject(new PostMessageTransportError('Communication channel could not be established within a reasonable time'));
|
|
100
|
+
},
|
|
101
|
+
onPendingTimeout: () => {
|
|
102
|
+
if (this.#options.closeOnPendingTimeout) {
|
|
103
|
+
signerWindow.close();
|
|
104
|
+
}
|
|
105
|
+
reject(new PostMessageTransportError('Communication channel was pending for too long'));
|
|
106
|
+
},
|
|
107
|
+
onDisconnect: () => channel.close(),
|
|
108
|
+
onStatusChange: status => channel.changeStatus(status),
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=postMessageTransport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postMessageTransport.js","sourceRoot":"","sources":["../../../src/web/postMessageTransport.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@icp-sdk/signer",
|
|
3
|
+
"version": "5.2.0",
|
|
4
|
+
"author": "DFINITY Stiftung <sdk@dfinity.org>",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"description": "Library to interact with signers on the Internet Computer",
|
|
7
|
+
"homepage": "https://js.icp.build/signer/",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/dfinity/icp-js-signer.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/dfinity/icp-js-signer/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"internet computer",
|
|
17
|
+
"internet-computer",
|
|
18
|
+
"ic",
|
|
19
|
+
"dfinity",
|
|
20
|
+
"signer",
|
|
21
|
+
"wallet",
|
|
22
|
+
"actor",
|
|
23
|
+
"dfx",
|
|
24
|
+
"canister",
|
|
25
|
+
"candid",
|
|
26
|
+
"motoko",
|
|
27
|
+
"javascript",
|
|
28
|
+
"typescript",
|
|
29
|
+
"blockchain",
|
|
30
|
+
"crypto",
|
|
31
|
+
"distributed",
|
|
32
|
+
"api",
|
|
33
|
+
"sdk"
|
|
34
|
+
],
|
|
35
|
+
"type": "module",
|
|
36
|
+
"types": "./lib/esm/index.d.ts",
|
|
37
|
+
"exports": {
|
|
38
|
+
".": {
|
|
39
|
+
"types": "./lib/esm/index.d.ts",
|
|
40
|
+
"import": "./lib/esm/index.js",
|
|
41
|
+
"default": "./lib/esm/index.js"
|
|
42
|
+
},
|
|
43
|
+
"./agent": {
|
|
44
|
+
"types": "./lib/esm/agent/index.d.ts",
|
|
45
|
+
"import": "./lib/esm/agent/index.js",
|
|
46
|
+
"default": "./lib/esm/agent/index.js"
|
|
47
|
+
},
|
|
48
|
+
"./web": {
|
|
49
|
+
"types": "./lib/esm/web/index.d.ts",
|
|
50
|
+
"import": "./lib/esm/web/index.js",
|
|
51
|
+
"default": "./lib/esm/web/index.js"
|
|
52
|
+
},
|
|
53
|
+
"./extension": {
|
|
54
|
+
"types": "./lib/esm/extension/index.d.ts",
|
|
55
|
+
"import": "./lib/esm/extension/index.js",
|
|
56
|
+
"default": "./lib/esm/extension/index.js"
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"build": "tsc -p tsconfig.esm.json && npm run lint:package",
|
|
61
|
+
"test": "vitest run",
|
|
62
|
+
"test:e2e": "npm run build && npm run build:e2e && playwright test",
|
|
63
|
+
"build:e2e": "cd e2e/fixtures && esbuild relying-party.ts mock-wallet.ts mock-auth-provider.ts --bundle --format=iife --outdir=. --out-extension:.js=.bundle.js --alias:@icp-sdk/signer=../../lib/esm/index.js --alias:@icp-sdk/signer/web=../../lib/esm/web/index.js --alias:@icp-sdk/signer/extension=../../lib/esm/extension/index.js --alias:@icp-sdk/signer/agent=../../lib/esm/agent/index.js",
|
|
64
|
+
"lint": "eslint src/",
|
|
65
|
+
"lint:fix": "eslint --fix src/",
|
|
66
|
+
"lint:package": "publint --strict",
|
|
67
|
+
"attw": "attw --pack .",
|
|
68
|
+
"docs": "cd docs && npm run build",
|
|
69
|
+
"size": "size-limit --json",
|
|
70
|
+
"prettier:check": "npx -p prettier -p pretty-quick pretty-quick --check --branch main",
|
|
71
|
+
"prettier:format": "npx -p prettier -p pretty-quick pretty-quick --branch main",
|
|
72
|
+
"prepare": "husky"
|
|
73
|
+
},
|
|
74
|
+
"peerDependencies": {
|
|
75
|
+
"@icp-sdk/core": "^5"
|
|
76
|
+
},
|
|
77
|
+
"size-limit": [
|
|
78
|
+
{
|
|
79
|
+
"name": "@icp-sdk/signer",
|
|
80
|
+
"path": "./lib/esm/index.js",
|
|
81
|
+
"limit": "15 kb"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"name": "@icp-sdk/signer/agent",
|
|
85
|
+
"path": "./lib/esm/agent/index.js",
|
|
86
|
+
"limit": "15 kb"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"name": "@icp-sdk/signer/web",
|
|
90
|
+
"path": "./lib/esm/web/index.js",
|
|
91
|
+
"limit": "15 kb"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"name": "@icp-sdk/signer/extension",
|
|
95
|
+
"path": "./lib/esm/extension/index.js",
|
|
96
|
+
"limit": "15 kb"
|
|
97
|
+
}
|
|
98
|
+
],
|
|
99
|
+
"devDependencies": {
|
|
100
|
+
"@arethetypeswrong/cli": "^0.18.2",
|
|
101
|
+
"@eslint/js": "^10.0.1",
|
|
102
|
+
"@playwright/test": "^1.58.2",
|
|
103
|
+
"@size-limit/esbuild": "^12.0.1",
|
|
104
|
+
"@size-limit/preset-small-lib": "^12.0.1",
|
|
105
|
+
"@tsconfig/node22": "^22.0.5",
|
|
106
|
+
"@types/node": "^25.5.0",
|
|
107
|
+
"@typescript-eslint/eslint-plugin": "^8.58.0",
|
|
108
|
+
"@typescript-eslint/parser": "^8.58.0",
|
|
109
|
+
"esbuild": "^0.27.4",
|
|
110
|
+
"eslint": "^10.1.0",
|
|
111
|
+
"eslint-plugin-jsdoc": "^62.8.1",
|
|
112
|
+
"globals": "^17.4.0",
|
|
113
|
+
"husky": "^9.1.7",
|
|
114
|
+
"prettier": "^3.8.1",
|
|
115
|
+
"pretty-quick": "^4.2.2",
|
|
116
|
+
"publint": "^0.3.18",
|
|
117
|
+
"serve": "^14.2.6",
|
|
118
|
+
"size-limit": "^12.0.1",
|
|
119
|
+
"typescript": "^5.9.3",
|
|
120
|
+
"vitest": "^4.1.1"
|
|
121
|
+
}
|
|
122
|
+
}
|