phantasma-sdk-ts 0.10.1 → 0.11.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.
|
@@ -131,11 +131,23 @@ class PhantasmaAPI {
|
|
|
131
131
|
this.nextRpcRequestId += 1;
|
|
132
132
|
return requestId;
|
|
133
133
|
}
|
|
134
|
+
rpcHeaders() {
|
|
135
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
136
|
+
if (this.apiKey) {
|
|
137
|
+
headers['X-Api-Key'] = this.apiKey;
|
|
138
|
+
}
|
|
139
|
+
return headers;
|
|
140
|
+
}
|
|
134
141
|
pingAsync(host) {
|
|
135
142
|
return new Promise((resolve, reject) => {
|
|
136
143
|
const started = new Date().getTime();
|
|
137
144
|
const http = new XMLHttpRequest();
|
|
138
145
|
http.open('GET', host + '/rpc', true);
|
|
146
|
+
// Under keys-only mode the health-check ping must present the key too, otherwise it gets 401 and
|
|
147
|
+
// the host is wrongly dropped from availableHosts during auto-discovery.
|
|
148
|
+
if (this.apiKey) {
|
|
149
|
+
http.setRequestHeader('X-Api-Key', this.apiKey);
|
|
150
|
+
}
|
|
139
151
|
http.timeout = 4500;
|
|
140
152
|
http.onreadystatechange = function () {
|
|
141
153
|
if (http.readyState == 4 && http.status == 200) {
|
|
@@ -166,6 +178,7 @@ class PhantasmaAPI {
|
|
|
166
178
|
this.host = defHost;
|
|
167
179
|
this.availableHosts = [];
|
|
168
180
|
this.maxRpcResponseBytes = normalizeMaxRpcResponseBytes(options.maxRpcResponseBytes);
|
|
181
|
+
this.apiKey = options.apiKey || undefined;
|
|
169
182
|
if (peersUrlJson != undefined && peersUrlJson != null) {
|
|
170
183
|
(0, cross_fetch_1.default)(peersUrlJson + '?_=' + new Date().getTime()).then(async (res) => {
|
|
171
184
|
const data = (await res.json());
|
|
@@ -201,7 +214,7 @@ class PhantasmaAPI {
|
|
|
201
214
|
params: params,
|
|
202
215
|
id: requestId,
|
|
203
216
|
}),
|
|
204
|
-
headers:
|
|
217
|
+
headers: this.rpcHeaders(),
|
|
205
218
|
});
|
|
206
219
|
}
|
|
207
220
|
catch (error) {
|
|
@@ -246,7 +259,7 @@ class PhantasmaAPI {
|
|
|
246
259
|
params: params,
|
|
247
260
|
id: requestId,
|
|
248
261
|
}),
|
|
249
|
-
headers:
|
|
262
|
+
headers: this.rpcHeaders(),
|
|
250
263
|
});
|
|
251
264
|
}
|
|
252
265
|
catch (error) {
|
|
@@ -279,6 +292,10 @@ class PhantasmaAPI {
|
|
|
279
292
|
this.maxRpcResponseBytes = normalizeMaxRpcResponseBytes(maxBytes);
|
|
280
293
|
return this;
|
|
281
294
|
}
|
|
295
|
+
setApiKey(apiKey) {
|
|
296
|
+
this.apiKey = apiKey || undefined;
|
|
297
|
+
return this;
|
|
298
|
+
}
|
|
282
299
|
setRpcHost(rpcHost) {
|
|
283
300
|
this.host = rpcHost;
|
|
284
301
|
}
|
|
@@ -125,11 +125,23 @@ export class PhantasmaAPI {
|
|
|
125
125
|
this.nextRpcRequestId += 1;
|
|
126
126
|
return requestId;
|
|
127
127
|
}
|
|
128
|
+
rpcHeaders() {
|
|
129
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
130
|
+
if (this.apiKey) {
|
|
131
|
+
headers['X-Api-Key'] = this.apiKey;
|
|
132
|
+
}
|
|
133
|
+
return headers;
|
|
134
|
+
}
|
|
128
135
|
pingAsync(host) {
|
|
129
136
|
return new Promise((resolve, reject) => {
|
|
130
137
|
const started = new Date().getTime();
|
|
131
138
|
const http = new XMLHttpRequest();
|
|
132
139
|
http.open('GET', host + '/rpc', true);
|
|
140
|
+
// Under keys-only mode the health-check ping must present the key too, otherwise it gets 401 and
|
|
141
|
+
// the host is wrongly dropped from availableHosts during auto-discovery.
|
|
142
|
+
if (this.apiKey) {
|
|
143
|
+
http.setRequestHeader('X-Api-Key', this.apiKey);
|
|
144
|
+
}
|
|
133
145
|
http.timeout = 4500;
|
|
134
146
|
http.onreadystatechange = function () {
|
|
135
147
|
if (http.readyState == 4 && http.status == 200) {
|
|
@@ -160,6 +172,7 @@ export class PhantasmaAPI {
|
|
|
160
172
|
this.host = defHost;
|
|
161
173
|
this.availableHosts = [];
|
|
162
174
|
this.maxRpcResponseBytes = normalizeMaxRpcResponseBytes(options.maxRpcResponseBytes);
|
|
175
|
+
this.apiKey = options.apiKey || undefined;
|
|
163
176
|
if (peersUrlJson != undefined && peersUrlJson != null) {
|
|
164
177
|
fetch(peersUrlJson + '?_=' + new Date().getTime()).then(async (res) => {
|
|
165
178
|
const data = (await res.json());
|
|
@@ -195,7 +208,7 @@ export class PhantasmaAPI {
|
|
|
195
208
|
params: params,
|
|
196
209
|
id: requestId,
|
|
197
210
|
}),
|
|
198
|
-
headers:
|
|
211
|
+
headers: this.rpcHeaders(),
|
|
199
212
|
});
|
|
200
213
|
}
|
|
201
214
|
catch (error) {
|
|
@@ -240,7 +253,7 @@ export class PhantasmaAPI {
|
|
|
240
253
|
params: params,
|
|
241
254
|
id: requestId,
|
|
242
255
|
}),
|
|
243
|
-
headers:
|
|
256
|
+
headers: this.rpcHeaders(),
|
|
244
257
|
});
|
|
245
258
|
}
|
|
246
259
|
catch (error) {
|
|
@@ -273,6 +286,10 @@ export class PhantasmaAPI {
|
|
|
273
286
|
this.maxRpcResponseBytes = normalizeMaxRpcResponseBytes(maxBytes);
|
|
274
287
|
return this;
|
|
275
288
|
}
|
|
289
|
+
setApiKey(apiKey) {
|
|
290
|
+
this.apiKey = apiKey || undefined;
|
|
291
|
+
return this;
|
|
292
|
+
}
|
|
276
293
|
setRpcHost(rpcHost) {
|
|
277
294
|
this.host = rpcHost;
|
|
278
295
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deeplink.d.ts","sourceRoot":"","sources":["../../../../src/link/v5/deeplink.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAG/C,uEAAuE;AACvE,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AAEjD;;2FAE2F;AAC3F,eAAO,MAAM,2BAA2B,SAAS,CAAC;AAElD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED;mFACmF;AACnF,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGxF;AAED,wFAAwF;AACxF,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAMhE;AAED,4EAA4E;AAC5E,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAIvF;AAED,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAMjE;AAmBD,MAAM,WAAW,wBAAwB;IACvC,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd,6FAA6F;IAC7F,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;6CAEyC;IACzC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,aAAa;IACrD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;IAC/C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAA4B;IACjD,OAAO,CAAC,cAAc,CAAC,CAA0B;IACjD,OAAO,CAAC,YAAY,CAAC,CAA4B;IACjD,OAAO,CAAC,MAAM,CAAS;gBAEX,OAAO,EAAE,wBAAwB;IAU7C,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAOzB,SAAS,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAIjD,OAAO,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAIjD;;;OAGG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;
|
|
1
|
+
{"version":3,"file":"deeplink.d.ts","sourceRoot":"","sources":["../../../../src/link/v5/deeplink.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAG/C,uEAAuE;AACvE,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AAEjD;;2FAE2F;AAC3F,eAAO,MAAM,2BAA2B,SAAS,CAAC;AAElD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED;mFACmF;AACnF,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGxF;AAED,wFAAwF;AACxF,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAMhE;AAED,4EAA4E;AAC5E,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAIvF;AAED,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAMjE;AAmBD,MAAM,WAAW,wBAAwB;IACvC,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd,6FAA6F;IAC7F,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;6CAEyC;IACzC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,aAAa;IACrD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;IAC/C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAA4B;IACjD,OAAO,CAAC,cAAc,CAAC,CAA0B;IACjD,OAAO,CAAC,YAAY,CAAC,CAA4B;IACjD,OAAO,CAAC,MAAM,CAAS;gBAEX,OAAO,EAAE,wBAAwB;IAU7C,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAOzB,SAAS,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAIjD,OAAO,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAIjD;;;OAGG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAuBhC,KAAK,IAAI,IAAI;CAOd"}
|
|
@@ -25,6 +25,8 @@ interface RpcPeer {
|
|
|
25
25
|
}
|
|
26
26
|
export interface PhantasmaAPIOptions {
|
|
27
27
|
maxRpcResponseBytes?: number;
|
|
28
|
+
/** Optional API key sent in the X-Api-Key header on every RPC request. */
|
|
29
|
+
apiKey?: string;
|
|
28
30
|
}
|
|
29
31
|
export declare const DEFAULT_MAX_RPC_RESPONSE_BYTES: number;
|
|
30
32
|
export declare class PhantasmaAPI {
|
|
@@ -34,12 +36,15 @@ export declare class PhantasmaAPI {
|
|
|
34
36
|
availableHosts: RpcPeer[];
|
|
35
37
|
maxRpcResponseBytes: number;
|
|
36
38
|
private nextRpcRequestId;
|
|
39
|
+
private apiKey?;
|
|
37
40
|
private nextJsonRpcRequestId;
|
|
41
|
+
private rpcHeaders;
|
|
38
42
|
pingAsync(host: string): Promise<number>;
|
|
39
43
|
constructor(defHost: string, peersUrlJson: string | undefined | null, nexus: string, options?: PhantasmaAPIOptions);
|
|
40
44
|
JSONRPCResult<T = unknown>(method: string, params: JsonRpcParam[]): Promise<RpcResult<T>>;
|
|
41
45
|
JSONRPC(method: string, params: JsonRpcParam[]): Promise<unknown>;
|
|
42
46
|
setMaxRpcResponseBytes(maxBytes: number): this;
|
|
47
|
+
setApiKey(apiKey: string): this;
|
|
43
48
|
setRpcHost(rpcHost: string): void;
|
|
44
49
|
setRpcByName(rpcName: string): void;
|
|
45
50
|
setNexus(nexus: string): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"phantasma.d.ts","sourceRoot":"","sources":["../../../src/rpc/phantasma.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAChG,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC1C,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,YAAY,EAIZ,SAAS,EACV,MAAM,iBAAiB,CAAC;AAEzB,UAAU,OAAO;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAoBD,MAAM,WAAW,mBAAmB;IAClC,mBAAmB,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"phantasma.d.ts","sourceRoot":"","sources":["../../../src/rpc/phantasma.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -7,11 +7,12 @@ This is an engineering specification and the source of truth for the dApp↔wall
|
|
|
7
7
|
connection protocol.
|
|
8
8
|
|
|
9
9
|
Design constraints:
|
|
10
|
+
|
|
10
11
|
- Own relay (self-hosted), JSON envelope, keep loopback.
|
|
11
12
|
- Deeplink ping-pong = primary path for the ~99% small requests AND relay-independent
|
|
12
13
|
(a relay outage must not break normal signing). Relay = large payloads (~1% "fat" tx)
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
- cross-device. Universal-link domain = the dedicated subdomain `link.phantasma.info`
|
|
15
|
+
(not the main site; see §17).
|
|
15
16
|
- Budget from chain: 1 MiB metadata struct (~750 KB image) / 32 MiB max tx.
|
|
16
17
|
|
|
17
18
|
---
|
|
@@ -19,6 +20,7 @@ Design constraints:
|
|
|
19
20
|
## 1. Goals / non-goals
|
|
20
21
|
|
|
21
22
|
Goals:
|
|
23
|
+
|
|
22
24
|
1. **iOS support** via deeplink (the immediate driver). Works without a wallet-hosted
|
|
23
25
|
local server (impossible on iOS).
|
|
24
26
|
2. **Remove the artificial size cap.** Carry transactions up to the real chain
|
|
@@ -32,12 +34,14 @@ Goals:
|
|
|
32
34
|
drift).
|
|
33
35
|
|
|
34
36
|
Non-goals (v5):
|
|
37
|
+
|
|
35
38
|
- Replacing on-chain data with hash-references; images stay on-chain, inside the tx.
|
|
36
39
|
- Multi-wallet-aggregator UX, WalletConnect interop (this protocol runs its own relay;
|
|
37
40
|
WC bridging could be a later additive capability).
|
|
38
41
|
- Changing any chain/validator/RPC behavior. v5 is purely the transport+envelope.
|
|
39
42
|
|
|
40
43
|
## 2. Terminology
|
|
44
|
+
|
|
41
45
|
- **dApp**: the requesting app (web page, native app, game). Holds NO keys.
|
|
42
46
|
- **Wallet**: holds keys, shows approval UI, signs. (PoltergeistLite desktop, Ecto
|
|
43
47
|
extension, ecto-mobile, future native apps.)
|
|
@@ -51,6 +55,7 @@ Non-goals (v5):
|
|
|
51
55
|
dApp and a wallet that can't reach each other directly (§6.4).
|
|
52
56
|
|
|
53
57
|
## 3. Architecture at a glance
|
|
58
|
+
|
|
54
59
|
```
|
|
55
60
|
┌─────────────── ONE JSON envelope (§4) ───────────────┐
|
|
56
61
|
│ │
|
|
@@ -60,6 +65,7 @@ Non-goals (v5):
|
|
|
60
65
|
selection: injected → loopback → deeplink(small) → relay(big/x-device)
|
|
61
66
|
resilience: deeplink(small) works even if relay is down.
|
|
62
67
|
```
|
|
68
|
+
|
|
63
69
|
The dApp calls high-level SDK methods (`signTransaction`, …). The SDK builds an
|
|
64
70
|
envelope and picks a transport. The wallet implements ONE envelope handler regardless
|
|
65
71
|
of transport. Wake/handoff on mobile is always via deeplink; data moves over the
|
|
@@ -71,28 +77,45 @@ All messages are UTF-8 JSON. Binary fields are **base64** (NOT hex - halves wire
|
|
|
71
77
|
size vs the old protocol). One logical request = one envelope; correlation by `id`.
|
|
72
78
|
|
|
73
79
|
Request:
|
|
80
|
+
|
|
74
81
|
```json
|
|
75
82
|
{
|
|
76
83
|
"plv": 5,
|
|
77
|
-
"id": "f1c2…",
|
|
78
|
-
"session": "s_9a8b…",
|
|
84
|
+
"id": "f1c2…", // unique per request (uuid v4 or monotonic+session)
|
|
85
|
+
"session": "s_9a8b…", // omitted only on the very first connect/pair
|
|
79
86
|
"method": "pha_signTransaction",
|
|
80
|
-
"params": {
|
|
87
|
+
"params": {
|
|
88
|
+
/* method-specific, named fields */
|
|
89
|
+
}
|
|
81
90
|
}
|
|
82
91
|
```
|
|
92
|
+
|
|
83
93
|
Success response:
|
|
94
|
+
|
|
84
95
|
```json
|
|
85
|
-
{
|
|
96
|
+
{
|
|
97
|
+
"plv": 5,
|
|
98
|
+
"id": "f1c2…",
|
|
99
|
+
"result": {
|
|
100
|
+
/* method-specific */
|
|
101
|
+
}
|
|
102
|
+
}
|
|
86
103
|
```
|
|
104
|
+
|
|
87
105
|
Error response:
|
|
106
|
+
|
|
88
107
|
```json
|
|
89
108
|
{ "plv": 5, "id": "f1c2…", "error": { "code": 4001, "message": "User rejected", "data": null } }
|
|
90
109
|
```
|
|
110
|
+
|
|
91
111
|
Wallet→dApp events (no `id` reply expected):
|
|
112
|
+
|
|
92
113
|
```json
|
|
93
114
|
{ "plv": 5, "type": "event", "session": "s_9a8b…", "event": "pha_accountsChanged", "data": { … } }
|
|
94
115
|
```
|
|
116
|
+
|
|
95
117
|
Rules:
|
|
118
|
+
|
|
96
119
|
- `plv` MUST be 5. A peer that doesn't recognize it errors `-32600`.
|
|
97
120
|
- Unknown `method` → `-32601`; bad params → `-32602`; malformed JSON → `-32700`.
|
|
98
121
|
- No positional args, no `,`/`/` delimiters, no version-gated arg layouts. New fields
|
|
@@ -102,9 +125,11 @@ Rules:
|
|
|
102
125
|
MUST correlate responses by `id` (no global single-in-flight flag like v1-v4).
|
|
103
126
|
|
|
104
127
|
## 5. Capability handshake (replaces the magic version int)
|
|
128
|
+
|
|
105
129
|
At connect/pair, both sides exchange capabilities once; cached in the session.
|
|
106
130
|
|
|
107
131
|
Wallet → dApp (in the `pha_connect` result):
|
|
132
|
+
|
|
108
133
|
```json
|
|
109
134
|
{
|
|
110
135
|
"wallet": { "name": "Poltergeist Lite", "version": "x.y.z", "icon": "https://…" },
|
|
@@ -118,6 +143,7 @@ Wallet → dApp (in the `pha_connect` result):
|
|
|
118
143
|
"account": { "address": "P2K…", "name": "…", "balances": [ … ] }
|
|
119
144
|
}
|
|
120
145
|
```
|
|
146
|
+
|
|
121
147
|
dApp → wallet (in `pha_connect` params): dApp metadata `{ name, url, icon, description }`,
|
|
122
148
|
requested `chains`, `methods`, desired `features`, and the dApp public key for E2E (§8).
|
|
123
149
|
|
|
@@ -130,6 +156,7 @@ features are additive capabilities; no new protocol version forks every implemen
|
|
|
130
156
|
The SDK selects in this order; each is described below.
|
|
131
157
|
|
|
132
158
|
### 6.1 Injected (browser extension wallet - Ecto)
|
|
159
|
+
|
|
133
160
|
- The extension injects a provider on the page. Envelopes pass page→content→background
|
|
134
161
|
via the extension messaging bridge (as today, but carrying the v5 envelope).
|
|
135
162
|
- Detection: provider object present on `window`.
|
|
@@ -137,6 +164,7 @@ The SDK selects in this order; each is described below.
|
|
|
137
164
|
- Best UX on desktop when the extension is installed.
|
|
138
165
|
|
|
139
166
|
### 6.2 Loopback (desktop browser/app ↔ desktop wallet) - KEPT
|
|
167
|
+
|
|
140
168
|
- The desktop wallet runs a **loopback-only** WebSocket server (rebuilt on a vetted
|
|
141
169
|
library, bound to 127.0.0.1/localhost ONLY - fix the v1-v4 `IPAddress.Any`), path
|
|
142
170
|
`/phantasma/v5`, carrying v5 envelopes (text frames; large messages allowed).
|
|
@@ -148,9 +176,11 @@ The SDK selects in this order; each is described below.
|
|
|
148
176
|
available; loopback callers without a verifiable origin get a clearly-labeled prompt.
|
|
149
177
|
|
|
150
178
|
### 6.3 Deeplink ping-pong (mobile, small requests) - PRIMARY, RELAY-INDEPENDENT
|
|
179
|
+
|
|
151
180
|
For the ~99% of requests that fit in a URL. No server, no relay.
|
|
152
181
|
|
|
153
182
|
Flow (request):
|
|
183
|
+
|
|
154
184
|
1. SDK serializes the envelope, seals it with the session key (§8, §18.2), base64url-encodes
|
|
155
185
|
the sealed frame, and builds a link routed by the pairing topic:
|
|
156
186
|
`https://link.phantasma.info/v5/req#t=<topic>&f=<b64url(sealed frame)>`
|
|
@@ -173,6 +203,7 @@ the SDK MUST fall back to the relay (§6.4). Small signs (authorize, signMessage
|
|
|
173
203
|
tx) stay on deeplink even with the relay down - satisfying the resilience rule.
|
|
174
204
|
|
|
175
205
|
dApp-type routing:
|
|
206
|
+
|
|
176
207
|
- NATIVE-app dApp ↔ wallet app: clean deeplink ping-pong (return via the dApp's own
|
|
177
208
|
scheme/universal link). Relay-independent.
|
|
178
209
|
- WEB-page dApp on mobile: the return would reopen the browser tab (page reload). So
|
|
@@ -181,6 +212,7 @@ dApp-type routing:
|
|
|
181
212
|
smooth normally, still works when the relay is down.
|
|
182
213
|
|
|
183
214
|
Security notes:
|
|
215
|
+
|
|
184
216
|
- Universal links are domain-verified (only the app the OS associated with
|
|
185
217
|
link.phantasma.info can claim them) → resistant to the custom-scheme hijack where a
|
|
186
218
|
malicious app registers `phantasma://`. Custom scheme is fallback only.
|
|
@@ -188,6 +220,7 @@ Security notes:
|
|
|
188
220
|
fallback scheme can't read request/result contents.
|
|
189
221
|
|
|
190
222
|
### 6.4 Relay (large payloads + cross-device) - self-hosted, E2E-blind
|
|
223
|
+
|
|
191
224
|
For "fat" transactions (image-bearing, up to chain limits) and desktop-dApp↔phone-wallet.
|
|
192
225
|
|
|
193
226
|
Model: a self-hosted pub/sub server. Each session has a **topic**. Either side
|
|
@@ -205,6 +238,7 @@ useful elsewhere - Rust dApp tooling / any future chain-aware relay feature - bu
|
|
|
205
238
|
core relay does not depend on it.)
|
|
206
239
|
|
|
207
240
|
Flow (request, mobile):
|
|
241
|
+
|
|
208
242
|
1. (Session already paired - see §7.) dApp encrypts the envelope, publishes to the topic.
|
|
209
243
|
2. dApp opens a small deeplink to WAKE the wallet (no payload in the URL - just a nudge to
|
|
210
244
|
foreground the wallet, which then drains its pairings' mailboxes): `https://link.phantasma.info/v5/wake`.
|
|
@@ -228,13 +262,14 @@ Relay outage degrades gracefully: big tx + cross-device unavailable; everyday si
|
|
|
228
262
|
keeps working.
|
|
229
263
|
|
|
230
264
|
## 7. Pairing & sessions
|
|
265
|
+
|
|
231
266
|
- **Pairing** (one-time) creates a Session. Two entry points:
|
|
232
267
|
- Same-device mobile: dApp opens a `…/link/v5/pair?…` universal link; wallet prompts
|
|
233
268
|
the user to approve, returns its capabilities + account + its E2E public key.
|
|
234
269
|
- Cross-device: dApp shows a QR encoding the pairing URI; the phone wallet scans it.
|
|
235
270
|
- **Session** (persistent on BOTH sides, surviving wallet restarts):
|
|
236
271
|
`{ sessionId, dappMeta, account, chains, methods, features, sharedKey(material),
|
|
237
|
-
|
|
272
|
+
createdAt, expiresAt }`. The user picks the lifetime at approval (session / 1h / 1d /
|
|
238
273
|
1mo / always). The wallet has a **revocation UI** listing active sessions.
|
|
239
274
|
- Re-connect: `pha_connect` with an existing `sessionId` resumes without a new prompt
|
|
240
275
|
(until expiry/revoke). Account/chain changes are pushed as events (§9).
|
|
@@ -261,6 +296,7 @@ keeps working.
|
|
|
261
296
|
full history.
|
|
262
297
|
|
|
263
298
|
## 8. Encryption & keys
|
|
299
|
+
|
|
264
300
|
- Every transport EXCEPT injected/loopback-with-trusted-origin carries E2E-encrypted
|
|
265
301
|
payloads. Deeplink and relay payloads are ALWAYS encrypted (they traverse the OS / the
|
|
266
302
|
relay).
|
|
@@ -299,7 +335,9 @@ keeps working.
|
|
|
299
335
|
## 9. Method catalog (v5)
|
|
300
336
|
|
|
301
337
|
### 9.1 Naming principles (durability)
|
|
338
|
+
|
|
302
339
|
The v1-v4 names are NOT durable and are redesigned here. Rules:
|
|
340
|
+
|
|
303
341
|
1. **No internal codenames in public names.** `signCarbonTxAndBroadcast` bakes the
|
|
304
342
|
Gen3 codename "Carbon" into the API - it ages the moment the codename changes or a
|
|
305
343
|
second format exists. Methods are named by WHAT they do; the tx format is advertised
|
|
@@ -315,12 +353,14 @@ The v1-v4 names are NOT durable and are redesigned here. Rules:
|
|
|
315
353
|
This maximizes durability and external-dev familiarity (and any future WC bridge).
|
|
316
354
|
5. Keep genuine Phantasma domain terms (e.g. `nexus`) as FIELDS, not as cryptic method
|
|
317
355
|
names.
|
|
318
|
-
Prefix: **`pha_`** (mirrors `eth_`).
|
|
356
|
+
Prefix: **`pha_`** (mirrors `eth_`).
|
|
319
357
|
|
|
320
358
|
Names are namespaced `pha_*`. Params/results are JSON objects (named). Binary = base64.
|
|
321
359
|
|
|
322
360
|
### 9.2 Methods
|
|
361
|
+
|
|
323
362
|
Connection / session:
|
|
363
|
+
|
|
324
364
|
- `pha_connect` - pair or resume. Params: dappMeta, requested chains/methods/features,
|
|
325
365
|
dApp pubkey. Result: capability handshake (§5) incl. account(s) + session.
|
|
326
366
|
- `pha_disconnect` - end session.
|
|
@@ -331,6 +371,7 @@ Connection / session:
|
|
|
331
371
|
`getWalletVersion` and `getPeer`).
|
|
332
372
|
|
|
333
373
|
Signing / sending (the transaction FORMAT is an explicit param - see §9.4):
|
|
374
|
+
|
|
334
375
|
- `pha_signMessage` - sign an arbitrary message (base64). Result: signature + the random
|
|
335
376
|
the wallet prepended. Non-tx-forgeable (§8). (was `signData`)
|
|
336
377
|
- `pha_signTransaction` - `{ format, tx }` → sign ONLY, return the assembled signed tx
|
|
@@ -342,6 +383,7 @@ Signing / sending (the transaction FORMAT is an explicit param - see §9.4):
|
|
|
342
383
|
broadcast / `signCarbonTxAndBroadcast`)
|
|
343
384
|
|
|
344
385
|
Read:
|
|
386
|
+
|
|
345
387
|
- `pha_invokeScript` - read-only VM invoke (eth_call-like); Result: decoded results[].
|
|
346
388
|
(was `invokeScript` / `invokeRawScript`)
|
|
347
389
|
|
|
@@ -354,21 +396,24 @@ Events (wallet→dApp): `pha_accountsChanged`, `pha_chainChanged`, `pha_sessionD
|
|
|
354
396
|
unsolicited connect result pushed right after pairing approval; see §9.5).
|
|
355
397
|
|
|
356
398
|
### 9.3 Legacy → v5 name map (for migration + the compat shim)
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
|
360
|
-
| `
|
|
361
|
-
| `
|
|
362
|
-
| `
|
|
363
|
-
| `
|
|
399
|
+
|
|
400
|
+
| v1-v4 | v5 |
|
|
401
|
+
| ----------------------------------------------------------------------- | ------------------------------------------- |
|
|
402
|
+
| `authorize` | `pha_connect` |
|
|
403
|
+
| `getAccount` | `pha_getAccounts` |
|
|
404
|
+
| `getNexus` | `pha_getChains` (nexus as field) |
|
|
405
|
+
| `getPeer` / `getWalletVersion` | `pha_getWalletInfo` |
|
|
406
|
+
| `signData` | `pha_signMessage` |
|
|
364
407
|
| `signTx` (no broadcast) / `signTxSignature` / `signPrebuiltTransaction` | `pha_signTransaction` (sign-only, `format`) |
|
|
365
|
-
| `signTx` (broadcast) / `signCarbonTxAndBroadcast`
|
|
366
|
-
| `invokeScript` / `invokeRawScript`
|
|
367
|
-
| `getN3Address`, `writeArchive`, `multiSig`
|
|
408
|
+
| `signTx` (broadcast) / `signCarbonTxAndBroadcast` | `pha_sendTransaction` (`format`) |
|
|
409
|
+
| `invokeScript` / `invokeRawScript` | `pha_invokeScript` |
|
|
410
|
+
| `getN3Address`, `writeArchive`, `multiSig` | DROPPED in v5 |
|
|
368
411
|
|
|
369
412
|
### 9.4 Transaction formats (how the wallet picks the RPC endpoint)
|
|
413
|
+
|
|
370
414
|
The chain accepts two DISTINCT signed-transaction formats, each via its OWN RPC
|
|
371
415
|
submission endpoint:
|
|
416
|
+
|
|
372
417
|
- **`script`** - the classic Phantasma `Transaction` (nexus/chain/script/payload/
|
|
373
418
|
expiration/signatures) → RPC `SendRawTransaction` (`Transaction.Unserialize`,
|
|
374
419
|
`network.SendRawPhantasmaTransaction`). Still used on Gen3 for VM/contract-lifecycle
|
|
@@ -387,11 +432,13 @@ format later = a new enum value + capability, never a new method. This is exactl
|
|
|
387
432
|
keeps the signing surface durable while honoring the real two-endpoint RPC.
|
|
388
433
|
|
|
389
434
|
### 9.5 Method contracts
|
|
435
|
+
|
|
390
436
|
Per-method params, results, and edge cases.
|
|
391
437
|
|
|
392
438
|
**`pha_connect`** - params `{ dapp:{name,url,icon,description}, pubkey, chains[],
|
|
393
439
|
methods[], features[] }`; result = capability handshake (§5) + the granted `account` +
|
|
394
440
|
`session{ id, expiresAt }`.
|
|
441
|
+
|
|
395
442
|
- The wallet returns the GRANTED capabilities, which MAY be a subset of what was
|
|
396
443
|
requested (WC-style partial approval); the dApp inspects what it actually got.
|
|
397
444
|
- Resume = `pha_connect` carrying an existing `session` id → no prompt unless
|
|
@@ -413,6 +460,7 @@ via the same node; no keys/approval involved.
|
|
|
413
460
|
|
|
414
461
|
**`pha_signMessage`** - params `{ message:base64, display?:string }`; result
|
|
415
462
|
`{ signature:base64, random:base64 }`. Construction + non-forgeability: §8.
|
|
463
|
+
|
|
416
464
|
- `signature` is the RAW 64-byte Ed25519 DETACHED signature over
|
|
417
465
|
`DOMAIN_TAG || random || message` (not a kind-prefixed envelope), signed by the
|
|
418
466
|
account's Phantasma key - verifiable with any NaCl stack against the public key
|
|
@@ -421,6 +469,7 @@ via the same node; no keys/approval involved.
|
|
|
421
469
|
**`pha_signTransaction`** - params `{ format:"script"|"carbon", tx:base64,
|
|
422
470
|
signatureKind?, pow? }`; result `{ signedTx:base64 }` (does NOT broadcast - the dApp
|
|
423
471
|
submits it). Covers the prebuilt-sign flow (e.g. token deployment).
|
|
472
|
+
|
|
424
473
|
- `pow` (ProofOfWork enum: None/Minimal/Moderate/Hard/Heavy/Extreme) is meaningful ONLY
|
|
425
474
|
for `format:"script"` (Phantasma-VM PoW); ignored for `carbon`.
|
|
426
475
|
- For PREBUILT script transactions the wallet does NOT mine pow: mining would mutate the
|
|
@@ -444,6 +493,7 @@ equally call the node directly.
|
|
|
444
493
|
**Events** (wallet→dApp): `pha_accountsChanged{accounts}`, `pha_chainChanged{chain}`,
|
|
445
494
|
`pha_sessionDeleted{session}`, `pha_sessionExpired{session}`,
|
|
446
495
|
`pha_sessionEstablished{<pha_connect result>}`.
|
|
496
|
+
|
|
447
497
|
- Transport caveat: live events require a PERSISTENT transport (injected / loopback /
|
|
448
498
|
relay subscription). A stateless deeplink-ping-pong session has no open channel, so it
|
|
449
499
|
does NOT receive pushed events; such a dApp re-queries account/chain on its next
|
|
@@ -458,6 +508,7 @@ equally call the node directly.
|
|
|
458
508
|
first connection is a single user gesture.
|
|
459
509
|
|
|
460
510
|
### 9.6 `format` values: `"script"` | `"carbon"`
|
|
511
|
+
|
|
461
512
|
Classic `Transaction` is, in practice, the **script-carrying** tx (its only present-day
|
|
462
513
|
use is a VM script), so `"script"` (not the ambiguous `"phantasma"`). Carbon stays
|
|
463
514
|
`"carbon"` (the real system term: `SendCarbonTransaction`/`CarbonBlob`). Nuance kept
|
|
@@ -465,7 +516,9 @@ honest: a Carbon `TxMsgPhantasma` ALSO wraps a script, but it is still the `carb
|
|
|
465
516
|
envelope - routing is by ENVELOPE/serialization, not by "contains a script".
|
|
466
517
|
|
|
467
518
|
### 9.7 Multi-platform signing
|
|
519
|
+
|
|
468
520
|
`signatureKind` selects WHICH KEY signs a **Phantasma** transaction/message:
|
|
521
|
+
|
|
469
522
|
- `Ed25519` → the Phantasma key; `ECDSA` → the secp256k1 key (used by ETH/BSC-interop
|
|
470
523
|
accounts). Both sign the SAME Phantasma tx bytes (`transaction.ToByteArray(false)`) - a
|
|
471
524
|
Phantasma tx can carry an ECDSA signature when the account is ETH-key-backed.
|
|
@@ -481,20 +534,23 @@ The value selects the key that signs the Phantasma payload. Native Ethereum/BSC
|
|
|
481
534
|
signing and broadcast is NOT part of v5 (a possible future additive capability).
|
|
482
535
|
|
|
483
536
|
## 10. Error codes
|
|
537
|
+
|
|
484
538
|
JSON-RPC reserved:
|
|
539
|
+
|
|
485
540
|
- `-32700` parse error, `-32600` invalid request, `-32601` method not found,
|
|
486
541
|
`-32602` invalid params, `-32603` internal error.
|
|
487
|
-
App-level (EIP-1193-aligned where sensible):
|
|
542
|
+
App-level (EIP-1193-aligned where sensible):
|
|
488
543
|
- `4001` user rejected, `4100` unauthorized / no valid session, `4900` wallet
|
|
489
544
|
disconnected / locked, `4902` unsupported chain.
|
|
490
|
-
Phantasma-specific:
|
|
545
|
+
Phantasma-specific:
|
|
491
546
|
- `5001` payload too large (carries `maxPayloadBytes` in `data`), `5002` nexus/chain
|
|
492
547
|
mismatch, `5003` unsupported signature kind, `5004` capability not supported,
|
|
493
548
|
`5100` session expired, `5101` session revoked.
|
|
494
|
-
Errors are STRUCTURED (`{code,message,data}`) - no more free-text string matching like
|
|
495
|
-
v1-v4 (e.g. `startsWith('nexus mismatch')`).
|
|
549
|
+
Errors are STRUCTURED (`{code,message,data}`) - no more free-text string matching like
|
|
550
|
+
v1-v4 (e.g. `startsWith('nexus mismatch')`).
|
|
496
551
|
|
|
497
552
|
## 11. Sizes & budget
|
|
553
|
+
|
|
498
554
|
- `maxPayloadBytes` advertised per transport in the handshake. Defaults: deeplink 8192
|
|
499
555
|
(conservative URL budget), loopback/relay 32 MiB (chain max-tx).
|
|
500
556
|
- An image-bearing token/NFT tx is bounded by the chain's 1 MiB metadata struct
|
|
@@ -507,6 +563,7 @@ v1-v4 (e.g. `startsWith('nexus mismatch')`).
|
|
|
507
563
|
`{ msgId, seq, total, chunk }` frames defined in §16, reassembled before decryption.
|
|
508
564
|
|
|
509
565
|
## 12. Backward compatibility & migration
|
|
566
|
+
|
|
510
567
|
- Wallets run BOTH dispatchers in parallel:
|
|
511
568
|
- Legacy v1-v4 string protocol (`{id},authorize/…`) - unchanged, for existing dApps.
|
|
512
569
|
- v5 envelope - detected by the structured `pha_connect` / `plv:5` handshake (and the
|
|
@@ -517,6 +574,7 @@ v1-v4 (e.g. `startsWith('nexus mismatch')`).
|
|
|
517
574
|
- ecto-mobile MUST stop vendoring an old SDK copy and consume the canonical SDK.
|
|
518
575
|
|
|
519
576
|
## 13. Reference implementation & conformance
|
|
577
|
+
|
|
520
578
|
- ONE reference implementation of the v5 envelope + transports in `phantasma-sdk-ts`
|
|
521
579
|
(`src/link/v5/`; canonical per workspace rule; never reimplement VM/script/serialization - reuse the
|
|
522
580
|
SDK). Wallets consume it: Ecto/ecto-mobile via the TS SDK; PoltergeistLite via the C#
|
|
@@ -526,6 +584,7 @@ v1-v4 (e.g. `startsWith('nexus mismatch')`).
|
|
|
526
584
|
cases, handshake, encryption KATs). Parity is already a mandatory SDK rule.
|
|
527
585
|
|
|
528
586
|
## 14. Security considerations (summary)
|
|
587
|
+
|
|
529
588
|
- E2E encryption on deeplink + relay; relay is blind; no secret in any URL (ECDH).
|
|
530
589
|
- Universal links (domain-verified) primary; custom scheme fallback only;
|
|
531
590
|
`link.phantasma.info` must serve `apple-app-site-association` + Android `assetlinks.json`.
|
|
@@ -538,6 +597,7 @@ v1-v4 (e.g. `startsWith('nexus mismatch')`).
|
|
|
538
597
|
- Relay abuse controls (rate-limit, topic auth, message TTL) - design in the relay spec.
|
|
539
598
|
|
|
540
599
|
## 15. Pairing URI + handshake
|
|
600
|
+
|
|
541
601
|
A pairing URI carries everything needed to bootstrap an encrypted session. It is shown as
|
|
542
602
|
a QR (cross-device: desktop dApp → phone wallet) or opened as a deeplink (same-device).
|
|
543
603
|
|
|
@@ -547,18 +607,22 @@ key-establishment method (full crypto in §18). Everything sensitive sits in the
|
|
|
547
607
|
logs never see it; the OS still hands the full URL (incl. fragment) to the app.
|
|
548
608
|
|
|
549
609
|
PRIMARY - universal link or QR (channels a relay/other app cannot intercept):
|
|
610
|
+
|
|
550
611
|
```
|
|
551
612
|
https://link.phantasma.info/v5/pair#v=5&t=<topic>&relay=<host>&sk=<symKey b64url>&meta=<dappMetaB64>
|
|
552
613
|
```
|
|
614
|
+
|
|
553
615
|
- `sk` = a random 32-byte SESSION KEY (CSPRNG). Safe to place here because a universal link
|
|
554
616
|
is domain-verified (only the link.phantasma.info-associated app receives it - no
|
|
555
617
|
scheme-squatter) and a QR is optical/user-mediated. The relay NEVER sees `sk`. → no MITM.
|
|
556
618
|
|
|
557
619
|
FALLBACK - custom scheme `phantasma://v5/pair#…` (last resort; a scheme-squatting app
|
|
558
620
|
could read it), so NO secret goes in it:
|
|
621
|
+
|
|
559
622
|
```
|
|
560
623
|
phantasma://v5/pair#v=5&t=<topic>&relay=<host>&pk=<dappX25519Pub b64url>
|
|
561
624
|
```
|
|
625
|
+
|
|
562
626
|
- `pk` = the dApp's EPHEMERAL X25519 PUBLIC key; the session key is derived by ECDH (§18).
|
|
563
627
|
No secret in the URL.
|
|
564
628
|
|
|
@@ -566,6 +630,7 @@ Common fields: `t` = topic (32 random bytes, b64url, the relay channel id); `rel
|
|
|
566
630
|
(or omitted → default); `meta` (dApp name/url/icon) MAY instead be sent encrypted.
|
|
567
631
|
|
|
568
632
|
Handshake:
|
|
633
|
+
|
|
569
634
|
1. dApp creates the topic + the key material (a `symKey` for the primary channel, OR an
|
|
570
635
|
ephemeral X25519 keypair for the custom-scheme fallback), builds the URI, subscribes to
|
|
571
636
|
the topic on the relay, and shows the QR / opens the deeplink.
|
|
@@ -587,11 +652,13 @@ Handshake:
|
|
|
587
652
|
Crypto construction, MITM analysis, nonces, and replay handling are specified in §18.
|
|
588
653
|
|
|
589
654
|
## 16. Relay protocol
|
|
655
|
+
|
|
590
656
|
A dumb, E2E-blind pub/sub over WSS. Self-hosted with the explorer (§6.4).
|
|
591
657
|
|
|
592
658
|
Frames (JSON): `{ op, topic, id?, payload? }`, `op ∈ { subscribe, unsubscribe, publish,
|
|
593
659
|
deliver, ack, error }`. `payload` is OPAQUE ciphertext (NaCl box, §8) - the relay never
|
|
594
660
|
decrypts.
|
|
661
|
+
|
|
595
662
|
- **Routing**: by `topic` (the 32-byte pairing id). The relay forwards a `publish` on a
|
|
596
663
|
topic to every other subscriber of that topic as `deliver`.
|
|
597
664
|
- **Mailbox / TTL**: if no subscriber is currently connected (e.g. the wallet hasn't been
|
|
@@ -616,9 +683,11 @@ decrypts.
|
|
|
616
683
|
- The relay needs NO Phantasma SDK and does NO chain logic.
|
|
617
684
|
|
|
618
685
|
## 17. Deeplinks & universal-link hosting
|
|
686
|
+
|
|
619
687
|
Paths under `https://link.phantasma.info/v5/` (and mirrored `phantasma://v5/…`):
|
|
688
|
+
|
|
620
689
|
- `/pair` - pairing (§15).
|
|
621
|
-
- `/req`
|
|
690
|
+
- `/req` - small same-device request: `#t=<topic>&f=<b64url(sealed frame)>`
|
|
622
691
|
(sealed payload in the fragment, routed by the pairing topic; the session id is inside the
|
|
623
692
|
envelope and the callback is the one fixed at pairing; size-gated per §6.3).
|
|
624
693
|
- `/wake` - foreground the wallet so it reconnects to the relay and drains its pairings'
|
|
@@ -627,6 +696,7 @@ Paths under `https://link.phantasma.info/v5/` (and mirrored `phantasma://v5/…`
|
|
|
627
696
|
link; web: an https URL) with `#plv=5&t=<topic>&f=<b64url(sealed frame)>`.
|
|
628
697
|
|
|
629
698
|
Hosting - on a DEDICATED SUBDOMAIN `link.phantasma.info`, NOT the main website:
|
|
699
|
+
|
|
630
700
|
- Why a subdomain: universal links / App Links are per-host; a subdomain is its own host
|
|
631
701
|
for verification, so it works identically to a root domain. This keeps the whole feature
|
|
632
702
|
off the main phantasma.info site. The ONLY change to existing infra is a DNS record.
|
|
@@ -647,12 +717,14 @@ Hosting - on a DEDICATED SUBDOMAIN `link.phantasma.info`, NOT the main website:
|
|
|
647
717
|
only; universal/app links are primary (domain-verified, anti-hijack).
|
|
648
718
|
|
|
649
719
|
## 18. Cryptographic construction
|
|
720
|
+
|
|
650
721
|
Primitive: NaCl **`secretbox` (XSalsa20-Poly1305)** for EVERY session message, under one
|
|
651
722
|
32-byte session key. X25519 is used ONLY for the custom-scheme fallback's key
|
|
652
723
|
establishment. Everything is standard NaCl, wire-interoperable across the §8 packages
|
|
653
724
|
(`tweetnacl` / `crypto_box` / `NaCl.Net` / `x/crypto/nacl` / libsodium).
|
|
654
725
|
|
|
655
726
|
### 18.1 Session-key establishment (channel decides)
|
|
727
|
+
|
|
656
728
|
Refinement of the earlier "no secret in URL" rule - the accurate rule is "no secret in a
|
|
657
729
|
HIJACKABLE url". A symmetric key is the simplest STRONG design where the delivery channel
|
|
658
730
|
is itself safe; ECDH is the fallback for the one hijackable channel:
|
|
@@ -665,7 +737,7 @@ is itself safe; ECDH is the fallback for the one hijackable channel:
|
|
|
665
737
|
than ECDH on these paths.
|
|
666
738
|
- **Custom scheme (FALLBACK, hijackable):** no `symKey` in the URL. X25519 ECDH instead -
|
|
667
739
|
dApp ephemeral pub in the URL (public, useless to a squatter), wallet ephemeral pub
|
|
668
|
-
returned over the relay, both derive the key via `box.before`.
|
|
740
|
+
returned over the relay, both derive the key via `box.before`.
|
|
669
741
|
- MITM analysis: only PUBLIC keys travel; a passive relay/3rd party cannot derive the
|
|
670
742
|
key. An ACTIVE compromised relay could swap the wallet's returned pubkey - but this is
|
|
671
743
|
ONE-SIDED: the relay can spoof the wallet→dApp direction, yet it CANNOT derive the
|
|
@@ -680,6 +752,7 @@ is itself safe; ECDH is the fallback for the one hijackable channel:
|
|
|
680
752
|
Either path yields one 32-byte session key; the channel is uniform `secretbox` thereafter.
|
|
681
753
|
|
|
682
754
|
### 18.2 Per-message
|
|
755
|
+
|
|
683
756
|
- `nonce` = 24 CSPRNG bytes per message (XSalsa20's 192-bit nonce → random nonces are
|
|
684
757
|
collision-safe; no cross-transport counter coordination needed).
|
|
685
758
|
- `ct` = `secretbox(utf8(envelope_json), nonce, sessionKey)`.
|
|
@@ -689,6 +762,7 @@ Either path yields one 32-byte session key; the channel is uniform `secretbox` t
|
|
|
689
762
|
`nonce`; the session binds a monotonic sequence.
|
|
690
763
|
|
|
691
764
|
### 18.3 Key hygiene
|
|
765
|
+
|
|
692
766
|
- The session key and any X25519 ephemerals are EPHEMERAL per pairing, in-memory only,
|
|
693
767
|
rotated on re-pair, destroyed on disconnect/expiry/revoke.
|
|
694
768
|
- They are NEVER the account signing key: Ed25519/ECDSA are used strictly for signing
|