@bananalink-test/hub 1.1.1
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/dist/index.cjs +364 -0
- package/dist/index.d.cts +146 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +146 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +353 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +44 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
let _bananalink_test_sdk_core = require("@bananalink-test/sdk-core");
|
|
3
|
+
|
|
4
|
+
//#region src/errors/BananalinkError.ts
|
|
5
|
+
var BananalinkError = class extends Error {
|
|
6
|
+
constructor(message, options) {
|
|
7
|
+
super(message, options);
|
|
8
|
+
this.name = "BananalinkError";
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/errors/ApiError.ts
|
|
14
|
+
var ApiError = class extends BananalinkError {
|
|
15
|
+
status;
|
|
16
|
+
body;
|
|
17
|
+
constructor(status, body) {
|
|
18
|
+
super(`API request failed with status ${status}`);
|
|
19
|
+
this.name = "ApiError";
|
|
20
|
+
this.status = status;
|
|
21
|
+
this.body = body;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/api/fetchAgent.ts
|
|
27
|
+
async function fetchAgent(apiUrl, agentPairingCode) {
|
|
28
|
+
const response = await fetch(`${apiUrl}/agents/${encodeURIComponent(agentPairingCode)}`);
|
|
29
|
+
if (!response.ok) {
|
|
30
|
+
const body = await response.json().catch(() => null);
|
|
31
|
+
throw new ApiError(response.status, body);
|
|
32
|
+
}
|
|
33
|
+
const body = await response.json();
|
|
34
|
+
if (!isAgent(body)) throw new ApiError(response.status, body);
|
|
35
|
+
return body;
|
|
36
|
+
}
|
|
37
|
+
function isAgent(value) {
|
|
38
|
+
if (typeof value !== "object" || value === null) return false;
|
|
39
|
+
const record = value;
|
|
40
|
+
return typeof record.agentId === "string" && typeof record.agentName === "string";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/api/fetchVapidKey.ts
|
|
45
|
+
async function fetchVapidKey(apiUrl = "https://api.dev.banana.link") {
|
|
46
|
+
const response = await fetch(`${apiUrl}/push/vapid-key`);
|
|
47
|
+
if (!response.ok) {
|
|
48
|
+
const body = await response.json().catch(() => null);
|
|
49
|
+
throw new ApiError(response.status, body);
|
|
50
|
+
}
|
|
51
|
+
const body = await response.json();
|
|
52
|
+
if (typeof body !== "object" || body === null || !("publicKey" in body)) throw new ApiError(response.status, body);
|
|
53
|
+
const { publicKey } = body;
|
|
54
|
+
if (typeof publicKey !== "string" || publicKey.length === 0) throw new ApiError(response.status, body);
|
|
55
|
+
return { publicKey };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region src/api/refreshHubTokens.ts
|
|
60
|
+
async function refreshHubTokens(apiUrl, refreshToken) {
|
|
61
|
+
const response = await fetch(`${apiUrl}/hubs/tokens/refresh`, {
|
|
62
|
+
method: "POST",
|
|
63
|
+
headers: { "Content-Type": "application/json" },
|
|
64
|
+
body: JSON.stringify({ refreshToken })
|
|
65
|
+
});
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
const responseBody = await response.json().catch(() => null);
|
|
68
|
+
throw new ApiError(response.status, responseBody);
|
|
69
|
+
}
|
|
70
|
+
const responseBody = await response.json().catch(() => null);
|
|
71
|
+
if (!isTokenPair$1(responseBody)) throw new ApiError(response.status, responseBody);
|
|
72
|
+
return responseBody;
|
|
73
|
+
}
|
|
74
|
+
function isTokenPair$1(value) {
|
|
75
|
+
if (typeof value !== "object" || value === null) return false;
|
|
76
|
+
return "accessToken" in value && typeof value.accessToken === "string" && "refreshToken" in value && typeof value.refreshToken === "string";
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/api/registerHub.ts
|
|
81
|
+
async function registerHub(apiUrl) {
|
|
82
|
+
const response = await fetch(`${apiUrl}/hubs`, { method: "POST" });
|
|
83
|
+
if (!response.ok) {
|
|
84
|
+
const responseBody = await response.json().catch(() => null);
|
|
85
|
+
throw new ApiError(response.status, responseBody);
|
|
86
|
+
}
|
|
87
|
+
const responseBody = await response.json().catch(() => null);
|
|
88
|
+
if (!isTokenPair(responseBody)) throw new ApiError(response.status, responseBody);
|
|
89
|
+
return responseBody;
|
|
90
|
+
}
|
|
91
|
+
function isTokenPair(value) {
|
|
92
|
+
if (typeof value !== "object" || value === null) return false;
|
|
93
|
+
return "accessToken" in value && typeof value.accessToken === "string" && "refreshToken" in value && typeof value.refreshToken === "string";
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
//#endregion
|
|
97
|
+
//#region src/api/deleteAgentTokens.ts
|
|
98
|
+
async function deleteAgentTokens(apiUrl, agentId, accessToken) {
|
|
99
|
+
const response = await fetch(`${apiUrl}/hubs/agents/${encodeURIComponent(agentId)}/tokens`, {
|
|
100
|
+
method: "DELETE",
|
|
101
|
+
headers: {
|
|
102
|
+
"Content-Type": "application/json",
|
|
103
|
+
Authorization: `Bearer ${accessToken}`
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
if (!response.ok) {
|
|
107
|
+
const responseBody = await response.json().catch(() => null);
|
|
108
|
+
throw new ApiError(response.status, responseBody);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
//#endregion
|
|
113
|
+
//#region src/errors/BindError.ts
|
|
114
|
+
var BindError = class extends BananalinkError {
|
|
115
|
+
constructor(error) {
|
|
116
|
+
super(`Hub bind failed with error: ${error}`);
|
|
117
|
+
this.error = error;
|
|
118
|
+
this.name = "BindError";
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
//#endregion
|
|
123
|
+
//#region src/errors/ConnectionError.ts
|
|
124
|
+
var ConnectionError = class extends BananalinkError {
|
|
125
|
+
constructor(message, options) {
|
|
126
|
+
super(message, options);
|
|
127
|
+
this.name = "ConnectionError";
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
//#endregion
|
|
132
|
+
//#region src/errors/NotConnectedError.ts
|
|
133
|
+
var NotConnectedError = class extends BananalinkError {
|
|
134
|
+
constructor() {
|
|
135
|
+
super("Hub is not connected. Call connect() first.");
|
|
136
|
+
this.name = "NotConnectedError";
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
//#endregion
|
|
141
|
+
//#region src/ws/createConnectionRequest.ts
|
|
142
|
+
function createConnectionRequest(params) {
|
|
143
|
+
return {
|
|
144
|
+
agentPairingCode: params.agentPairingCode,
|
|
145
|
+
agent: params.agent,
|
|
146
|
+
async approve() {
|
|
147
|
+
const authorizeMessage = {
|
|
148
|
+
type: "authorize",
|
|
149
|
+
code: params.agentPairingCode
|
|
150
|
+
};
|
|
151
|
+
params.ws.send(authorizeMessage);
|
|
152
|
+
},
|
|
153
|
+
async reject() {
|
|
154
|
+
const rejectMessage = {
|
|
155
|
+
type: "reject",
|
|
156
|
+
code: params.agentPairingCode
|
|
157
|
+
};
|
|
158
|
+
params.ws.send(rejectMessage);
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
//#endregion
|
|
164
|
+
//#region src/ws/createMessageRequest.ts
|
|
165
|
+
function createMessageRequest(message, ws) {
|
|
166
|
+
return {
|
|
167
|
+
messageId: message.messageId,
|
|
168
|
+
agentId: message.agentId,
|
|
169
|
+
method: message.method,
|
|
170
|
+
payload: message.payload,
|
|
171
|
+
respond(status, payloadResponse) {
|
|
172
|
+
const response = {
|
|
173
|
+
type: "message_response",
|
|
174
|
+
msgId: message.messageId,
|
|
175
|
+
status,
|
|
176
|
+
payloadResponse
|
|
177
|
+
};
|
|
178
|
+
ws.send(response);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region src/ws/createTransactionRequest.ts
|
|
185
|
+
function createTransactionRequest(message, ws) {
|
|
186
|
+
const base = createMessageRequest(message, ws);
|
|
187
|
+
return {
|
|
188
|
+
...base,
|
|
189
|
+
payload: base.payload[0],
|
|
190
|
+
approve(result) {
|
|
191
|
+
base.respond("approved", result);
|
|
192
|
+
},
|
|
193
|
+
reject(reason) {
|
|
194
|
+
base.respond("rejected", reason);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
//#endregion
|
|
200
|
+
//#region src/core/BananalinkHub.ts
|
|
201
|
+
var BananalinkHub = class BananalinkHub {
|
|
202
|
+
static DEFAULT_API_URL = "https://api.dev.banana.link";
|
|
203
|
+
static DEFAULT_WS_URL = "wss://ws.dev.banana.link";
|
|
204
|
+
static BIND_RESPONSE_TIMEOUT_MILLIS = 20 * 1e3;
|
|
205
|
+
apiUrl;
|
|
206
|
+
wsUrl;
|
|
207
|
+
ws = null;
|
|
208
|
+
accessToken = null;
|
|
209
|
+
transactionHandler = null;
|
|
210
|
+
unsubscribeMessages = null;
|
|
211
|
+
constructor(config) {
|
|
212
|
+
this.apiUrl = stripTrailingSlash(config?.apiUrl ?? BananalinkHub.DEFAULT_API_URL);
|
|
213
|
+
this.wsUrl = stripTrailingSlash(config?.wsUrl ?? BananalinkHub.DEFAULT_WS_URL);
|
|
214
|
+
}
|
|
215
|
+
async connect(accessToken) {
|
|
216
|
+
if (!accessToken.trim()) throw new BananalinkError("accessToken is required");
|
|
217
|
+
this.disconnect();
|
|
218
|
+
let transportHandle;
|
|
219
|
+
try {
|
|
220
|
+
transportHandle = await this.getTransportHandle();
|
|
221
|
+
} catch (error) {
|
|
222
|
+
throw new ConnectionError("Unable to establish hub websocket connection", { cause: error });
|
|
223
|
+
}
|
|
224
|
+
try {
|
|
225
|
+
await this.bind(transportHandle, accessToken);
|
|
226
|
+
this.accessToken = accessToken;
|
|
227
|
+
this.ws = (0, _bananalink_test_sdk_core.createReconnectingTransport)(transportHandle, {
|
|
228
|
+
reconnectTransport: async () => this.getTransportHandle(),
|
|
229
|
+
onReconnect: async (th) => this.bind(th, accessToken),
|
|
230
|
+
maxReconnectAttempts: 5,
|
|
231
|
+
baseDelayReconnectMs: 1e3
|
|
232
|
+
});
|
|
233
|
+
} catch (error) {
|
|
234
|
+
transportHandle.close();
|
|
235
|
+
throw error;
|
|
236
|
+
}
|
|
237
|
+
this.listenForMessages(this.ws);
|
|
238
|
+
}
|
|
239
|
+
disconnect() {
|
|
240
|
+
this.unsubscribeMessages?.();
|
|
241
|
+
this.unsubscribeMessages = null;
|
|
242
|
+
this.ws?.close();
|
|
243
|
+
this.ws = null;
|
|
244
|
+
}
|
|
245
|
+
subscribePush(subscription) {
|
|
246
|
+
if (!this.ws) throw new NotConnectedError();
|
|
247
|
+
if (!subscription.endpoint.trim()) throw new BananalinkError("subscription endpoint is required");
|
|
248
|
+
if (!subscription.keys.auth.trim()) throw new BananalinkError("subscription keys.auth is required");
|
|
249
|
+
if (!subscription.keys.p256dh.trim()) throw new BananalinkError("subscription keys.p256dh is required");
|
|
250
|
+
const message = {
|
|
251
|
+
type: "subscribe_push",
|
|
252
|
+
subscription
|
|
253
|
+
};
|
|
254
|
+
this.ws.send(message);
|
|
255
|
+
}
|
|
256
|
+
unsubscribePush(endpoint) {
|
|
257
|
+
if (!this.ws) throw new NotConnectedError();
|
|
258
|
+
if (!endpoint.trim()) throw new BananalinkError("subscription endpoint is required");
|
|
259
|
+
const message = {
|
|
260
|
+
type: "unsubscribe_push",
|
|
261
|
+
endpoint
|
|
262
|
+
};
|
|
263
|
+
this.ws.send(message);
|
|
264
|
+
}
|
|
265
|
+
onTransactionRequest(handler) {
|
|
266
|
+
this.transactionHandler = handler;
|
|
267
|
+
return () => {
|
|
268
|
+
this.transactionHandler = null;
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
async getConnectionRequest(params) {
|
|
272
|
+
if (!this.ws) throw new NotConnectedError();
|
|
273
|
+
if (!params.agentPairingCode.trim()) throw new BananalinkError("agentPairingCode is required");
|
|
274
|
+
const agent = await fetchAgent(this.apiUrl, params.agentPairingCode);
|
|
275
|
+
return createConnectionRequest({
|
|
276
|
+
agentPairingCode: params.agentPairingCode,
|
|
277
|
+
agent,
|
|
278
|
+
ws: this.ws
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
async revoke(params) {
|
|
282
|
+
if (!params.agentId.trim()) throw new BananalinkError("agentId is required");
|
|
283
|
+
if (!this.accessToken) throw new BananalinkError("accessToken is required");
|
|
284
|
+
await deleteAgentTokens(this.apiUrl, params.agentId, this.accessToken);
|
|
285
|
+
}
|
|
286
|
+
listenForMessages(ws) {
|
|
287
|
+
this.unsubscribeMessages = ws.onMessage((payload) => {
|
|
288
|
+
if (!(0, _bananalink_test_sdk_core.isMessageRequestMessage)(payload)) return;
|
|
289
|
+
if (payload.method === _bananalink_test_sdk_core.MESSAGE_METHOD_SEND_TRANSACTION && this.transactionHandler) this.dispatchTransactionRequest(this.transactionHandler, payload, ws);
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
dispatchTransactionRequest(handler, payload, ws) {
|
|
293
|
+
const request = createTransactionRequest(payload, ws);
|
|
294
|
+
const safeReject = (error) => {
|
|
295
|
+
try {
|
|
296
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
297
|
+
request.reject(`transaction handler failed: ${message}`);
|
|
298
|
+
} catch {}
|
|
299
|
+
};
|
|
300
|
+
try {
|
|
301
|
+
Promise.resolve(handler(request)).catch(safeReject);
|
|
302
|
+
} catch (error) {
|
|
303
|
+
safeReject(error);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
async getTransportHandle() {
|
|
307
|
+
return await (0, _bananalink_test_sdk_core.connectWebSocket)({
|
|
308
|
+
url: this.wsUrl,
|
|
309
|
+
pingIntervalMs: 3e4,
|
|
310
|
+
pongTimeoutMs: 5e3,
|
|
311
|
+
maxReconnectAttempts: 0
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
async bind(ws, accessToken) {
|
|
315
|
+
try {
|
|
316
|
+
await (0, _bananalink_test_sdk_core.bindTransport)(ws, accessToken, {
|
|
317
|
+
timeoutMs: BananalinkHub.BIND_RESPONSE_TIMEOUT_MILLIS,
|
|
318
|
+
createClosedError: () => new ConnectionError("Connection closed unexpectedly while waiting for hub bind response"),
|
|
319
|
+
createTimeoutError: () => new ConnectionError("Timed out waiting for hub bind response")
|
|
320
|
+
});
|
|
321
|
+
} catch (error) {
|
|
322
|
+
if (error instanceof _bananalink_test_sdk_core.BindTransportError) throw new BindError(error.code);
|
|
323
|
+
throw error;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
function stripTrailingSlash(url) {
|
|
328
|
+
return url.replace(/\/+$/, "");
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
//#endregion
|
|
332
|
+
//#region src/utils/buildSiweMessage.ts
|
|
333
|
+
function buildSiweMessage(params) {
|
|
334
|
+
const issuedAt = params.issuedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
335
|
+
return `${params.domain} wants you to sign in with your Ethereum account:\n${params.address}\n\n${params.statement}\n\nURI: ${params.uri}\nVersion: 1\nChain ID: ${params.chainId}\nNonce: ${params.nonce}\nIssued At: ${issuedAt}`;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
//#endregion
|
|
339
|
+
//#region src/utils/parseDeepLink.ts
|
|
340
|
+
function parseDeepLink(deepLink) {
|
|
341
|
+
let url;
|
|
342
|
+
try {
|
|
343
|
+
url = new URL(deepLink);
|
|
344
|
+
} catch (error) {
|
|
345
|
+
throw new BananalinkError("Invalid deep link URL", { cause: error });
|
|
346
|
+
}
|
|
347
|
+
const code = url.searchParams.get("code");
|
|
348
|
+
if (!code) throw new BananalinkError("Invalid deep link: missing agent pairing code");
|
|
349
|
+
return { code };
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
//#endregion
|
|
353
|
+
exports.ApiError = ApiError;
|
|
354
|
+
exports.BananalinkError = BananalinkError;
|
|
355
|
+
exports.BananalinkHub = BananalinkHub;
|
|
356
|
+
exports.BindError = BindError;
|
|
357
|
+
exports.ConnectionError = ConnectionError;
|
|
358
|
+
exports.NotConnectedError = NotConnectedError;
|
|
359
|
+
exports.buildSiweMessage = buildSiweMessage;
|
|
360
|
+
exports.fetchAgent = fetchAgent;
|
|
361
|
+
exports.fetchVapidKey = fetchVapidKey;
|
|
362
|
+
exports.parseDeepLink = parseDeepLink;
|
|
363
|
+
exports.refreshHubTokens = refreshHubTokens;
|
|
364
|
+
exports.registerHub = registerHub;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { Agent, Agent as Agent$1, ConnectionRequestParams, ConnectionRequestParams as ConnectionRequestParams$1, DeepLinkParams, DeepLinkParams as DeepLinkParams$1, EthSendTransactionParams, EthSendTransactionParams as EthSendTransactionParams$1, EthSendTransactionResult, EthSendTransactionResult as EthSendTransactionResult$1 } from "@bananalink-test/sdk-core";
|
|
2
|
+
|
|
3
|
+
//#region src/api/fetchAgent.d.ts
|
|
4
|
+
declare function fetchAgent(apiUrl: string, agentPairingCode: string): Promise<Agent$1>;
|
|
5
|
+
//#endregion
|
|
6
|
+
//#region src/api/fetchVapidKey.d.ts
|
|
7
|
+
declare function fetchVapidKey(apiUrl?: string): Promise<{
|
|
8
|
+
publicKey: string;
|
|
9
|
+
}>;
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/types/TokenPair.d.ts
|
|
12
|
+
type TokenPair = {
|
|
13
|
+
accessToken: string;
|
|
14
|
+
refreshToken: string;
|
|
15
|
+
};
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/api/refreshHubTokens.d.ts
|
|
18
|
+
declare function refreshHubTokens(apiUrl: string, refreshToken: string): Promise<TokenPair>;
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/api/registerHub.d.ts
|
|
21
|
+
declare function registerHub(apiUrl: string): Promise<TokenPair>;
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/types/PushSubscriptionParams.d.ts
|
|
24
|
+
type PushSubscriptionParams = {
|
|
25
|
+
endpoint: string;
|
|
26
|
+
keys: {
|
|
27
|
+
p256dh: string;
|
|
28
|
+
auth: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/types/RevokeParams.d.ts
|
|
33
|
+
interface RevokeParams {
|
|
34
|
+
agentId: string;
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region src/ws/MessageRequest.d.ts
|
|
38
|
+
interface MessageRequest<TPayload> {
|
|
39
|
+
readonly messageId: string;
|
|
40
|
+
readonly agentId: string;
|
|
41
|
+
readonly method: string;
|
|
42
|
+
readonly payload: TPayload;
|
|
43
|
+
respond(status: string, payloadResponse?: unknown): void;
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/ws/TransactionRequest.d.ts
|
|
47
|
+
interface TransactionRequest extends MessageRequest<EthSendTransactionParams$1> {
|
|
48
|
+
approve(result: EthSendTransactionResult$1): void;
|
|
49
|
+
reject(reason?: string): void;
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region src/types/TransactionRequestHandler.d.ts
|
|
53
|
+
type TransactionRequestHandler = (request: TransactionRequest) => void | Promise<void>;
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/ws/ConnectionRequest.d.ts
|
|
56
|
+
interface ConnectionRequest {
|
|
57
|
+
readonly agentPairingCode: string;
|
|
58
|
+
readonly agent: Agent$1;
|
|
59
|
+
approve(): Promise<void>;
|
|
60
|
+
reject(): Promise<void>;
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/core/BananalinkHubConfig.d.ts
|
|
64
|
+
interface BananalinkHubConfig {
|
|
65
|
+
apiUrl?: string;
|
|
66
|
+
wsUrl?: string;
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/core/BananalinkHub.d.ts
|
|
70
|
+
declare class BananalinkHub {
|
|
71
|
+
private static readonly DEFAULT_API_URL;
|
|
72
|
+
private static readonly DEFAULT_WS_URL;
|
|
73
|
+
private static readonly BIND_RESPONSE_TIMEOUT_MILLIS;
|
|
74
|
+
private readonly apiUrl;
|
|
75
|
+
private readonly wsUrl;
|
|
76
|
+
private ws;
|
|
77
|
+
private accessToken;
|
|
78
|
+
private transactionHandler;
|
|
79
|
+
private unsubscribeMessages;
|
|
80
|
+
constructor(config?: BananalinkHubConfig);
|
|
81
|
+
connect(accessToken: string): Promise<void>;
|
|
82
|
+
disconnect(): void;
|
|
83
|
+
subscribePush(subscription: PushSubscriptionParams): void;
|
|
84
|
+
unsubscribePush(endpoint: string): void;
|
|
85
|
+
onTransactionRequest(handler: TransactionRequestHandler): () => void;
|
|
86
|
+
getConnectionRequest(params: ConnectionRequestParams$1): Promise<ConnectionRequest>;
|
|
87
|
+
revoke(params: RevokeParams): Promise<void>;
|
|
88
|
+
private listenForMessages;
|
|
89
|
+
private dispatchTransactionRequest;
|
|
90
|
+
private getTransportHandle;
|
|
91
|
+
private bind;
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/errors/BananalinkError.d.ts
|
|
95
|
+
declare class BananalinkError extends Error {
|
|
96
|
+
constructor(message: string, options?: ErrorOptions);
|
|
97
|
+
}
|
|
98
|
+
//#endregion
|
|
99
|
+
//#region src/errors/ApiError.d.ts
|
|
100
|
+
declare class ApiError extends BananalinkError {
|
|
101
|
+
readonly status: number;
|
|
102
|
+
readonly body: unknown;
|
|
103
|
+
constructor(status: number, body: unknown);
|
|
104
|
+
}
|
|
105
|
+
//#endregion
|
|
106
|
+
//#region src/errors/BindError.d.ts
|
|
107
|
+
declare class BindError extends BananalinkError {
|
|
108
|
+
readonly error: 'INVALID_JWT' | 'JWT_EXPIRED';
|
|
109
|
+
constructor(error: 'INVALID_JWT' | 'JWT_EXPIRED');
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
112
|
+
//#region src/errors/ConnectionError.d.ts
|
|
113
|
+
declare class ConnectionError extends BananalinkError {
|
|
114
|
+
constructor(message: string, options?: ErrorOptions);
|
|
115
|
+
}
|
|
116
|
+
//#endregion
|
|
117
|
+
//#region src/errors/NotConnectedError.d.ts
|
|
118
|
+
declare class NotConnectedError extends BananalinkError {
|
|
119
|
+
constructor();
|
|
120
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region src/types/BuildSiweMessageParams.d.ts
|
|
123
|
+
interface BuildSiweMessageParams {
|
|
124
|
+
domain: string;
|
|
125
|
+
address: string;
|
|
126
|
+
uri: string;
|
|
127
|
+
statement: string;
|
|
128
|
+
nonce: string;
|
|
129
|
+
chainId: number;
|
|
130
|
+
issuedAt?: string;
|
|
131
|
+
}
|
|
132
|
+
//#endregion
|
|
133
|
+
//#region src/types/Signer.d.ts
|
|
134
|
+
interface Signer {
|
|
135
|
+
address: string;
|
|
136
|
+
signMessage: (message: string) => Promise<string>;
|
|
137
|
+
}
|
|
138
|
+
//#endregion
|
|
139
|
+
//#region src/utils/buildSiweMessage.d.ts
|
|
140
|
+
declare function buildSiweMessage(params: BuildSiweMessageParams): string;
|
|
141
|
+
//#endregion
|
|
142
|
+
//#region src/utils/parseDeepLink.d.ts
|
|
143
|
+
declare function parseDeepLink(deepLink: string): DeepLinkParams$1;
|
|
144
|
+
//#endregion
|
|
145
|
+
export { type Agent, ApiError, BananalinkError, BananalinkHub, type BananalinkHubConfig, BindError, type BuildSiweMessageParams, ConnectionError, type ConnectionRequest, type ConnectionRequestParams, type DeepLinkParams, type EthSendTransactionParams, type EthSendTransactionResult, type MessageRequest, NotConnectedError, type PushSubscriptionParams, type RevokeParams, type Signer, type TokenPair, type TransactionRequest, type TransactionRequestHandler, buildSiweMessage, fetchAgent, fetchVapidKey, parseDeepLink, refreshHubTokens, registerHub };
|
|
146
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/api/fetchAgent.ts","../src/api/fetchVapidKey.ts","../src/types/TokenPair.ts","../src/api/refreshHubTokens.ts","../src/api/registerHub.ts","../src/types/PushSubscriptionParams.ts","../src/types/RevokeParams.ts","../src/ws/MessageRequest.ts","../src/ws/TransactionRequest.ts","../src/types/TransactionRequestHandler.ts","../src/ws/ConnectionRequest.ts","../src/core/BananalinkHubConfig.ts","../src/core/BananalinkHub.ts","../src/errors/BananalinkError.ts","../src/errors/ApiError.ts","../src/errors/BindError.ts","../src/errors/ConnectionError.ts","../src/errors/NotConnectedError.ts","../src/types/BuildSiweMessageParams.ts","../src/types/Signer.ts","../src/utils/buildSiweMessage.ts","../src/utils/parseDeepLink.ts"],"mappings":";;;iBAGsB,UAAA,CAAW,MAAA,UAAgB,gBAAA,WAA2B,OAAA,CAAQ,OAAA;;;iBCD9D,aAAA,CAAc,MAAA,YAAiD,OAAA;EAAU,SAAA;AAAA;;;KCFnF,SAAA;EACV,WAAA;EACA,YAAA;AAAA;;;iBCCoB,gBAAA,CAAiB,MAAA,UAAgB,YAAA,WAAuB,OAAA,CAAQ,SAAA;;;iBCAhE,WAAA,CAAY,MAAA,WAAiB,OAAA,CAAQ,SAAA;;;KCH/C,sBAAA;EAA2B,QAAA;EAAkB,IAAA;IAAQ,MAAA;IAAgB,IAAA;EAAA;AAAA;;;UCAhE,YAAA;EACf,OAAA;AAAA;;;UCDe,cAAA;EAAA,SACN,SAAA;EAAA,SACA,OAAA;EAAA,SACA,MAAA;EAAA,SACA,OAAA,EAAS,QAAA;EAClB,OAAA,CAAQ,MAAA,UAAgB,eAAA;AAAA;;;UCFT,kBAAA,SAA2B,cAAA,CAAe,0BAAA;EACzD,OAAA,CAAQ,MAAA,EAAQ,0BAAA;EAChB,MAAA,CAAO,MAAA;AAAA;;;KCHG,yBAAA,IAA6B,OAAA,EAAS,kBAAA,YAA8B,OAAA;;;UCA/D,iBAAA;EAAA,SACN,gBAAA;EAAA,SACA,KAAA,EAAO,OAAA;EAChB,OAAA,IAAW,OAAA;EACX,MAAA,IAAU,OAAA;AAAA;;;UCNK,mBAAA;EACf,MAAA;EACA,KAAA;AAAA;;;cCyBW,aAAA;EAAA,wBACa,eAAA;EAAA,wBACA,cAAA;EAAA,wBACA,4BAAA;EAAA,iBAEP,MAAA;EAAA,iBACA,KAAA;EAAA,QACT,EAAA;EAAA,QACA,WAAA;EAAA,QACA,kBAAA;EAAA,QACA,mBAAA;cAEI,MAAA,GAAS,mBAAA;EAKf,OAAA,CAAQ,WAAA,WAAsB,OAAA;EAgCpC,UAAA,CAAA;EAOA,aAAA,CAAc,YAAA,EAAc,sBAAA;EAyB5B,eAAA,CAAgB,QAAA;EAiBhB,oBAAA,CAAqB,OAAA,EAAS,yBAAA;EAQxB,oBAAA,CAAqB,MAAA,EAAQ,yBAAA,GAA0B,OAAA,CAAQ,iBAAA;EAkB/D,MAAA,CAAO,MAAA,EAAQ,YAAA,GAAe,OAAA;EAAA,QAW5B,iBAAA;EAAA,QAYA,0BAAA;EAAA,QAqBM,kBAAA;EAAA,QASA,IAAA;AAAA;;;cC5MH,eAAA,SAAwB,KAAA;cACvB,OAAA,UAAiB,OAAA,GAAU,YAAA;AAAA;;;cCC5B,QAAA,SAAiB,eAAA;EAAA,SACZ,MAAA;EAAA,SACA,IAAA;cAEJ,MAAA,UAAgB,IAAA;AAAA;;;cCJjB,SAAA,SAAkB,eAAA;EAAA,SACD,KAAA;cAAA,KAAA;AAAA;;;cCDjB,eAAA,SAAwB,eAAA;cACvB,OAAA,UAAiB,OAAA,GAAU,YAAA;AAAA;;;cCD5B,iBAAA,SAA0B,eAAA;EAAA,WAAA,CAAA;AAAA;;;UCFtB,sBAAA;EACf,MAAA;EACA,OAAA;EACA,GAAA;EACA,SAAA;EACA,KAAA;EACA,OAAA;EACA,QAAA;AAAA;;;UCPe,MAAA;EACf,OAAA;EACA,WAAA,GAAc,OAAA,aAAoB,OAAA;AAAA;;;iBCApB,gBAAA,CAAiB,MAAA,EAAQ,sBAAA;;;iBCCzB,aAAA,CAAc,QAAA,WAAmB,gBAAA"}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { Agent, Agent as Agent$1, ConnectionRequestParams, ConnectionRequestParams as ConnectionRequestParams$1, DeepLinkParams, DeepLinkParams as DeepLinkParams$1, EthSendTransactionParams, EthSendTransactionParams as EthSendTransactionParams$1, EthSendTransactionResult, EthSendTransactionResult as EthSendTransactionResult$1 } from "@bananalink-test/sdk-core";
|
|
2
|
+
|
|
3
|
+
//#region src/api/fetchAgent.d.ts
|
|
4
|
+
declare function fetchAgent(apiUrl: string, agentPairingCode: string): Promise<Agent$1>;
|
|
5
|
+
//#endregion
|
|
6
|
+
//#region src/api/fetchVapidKey.d.ts
|
|
7
|
+
declare function fetchVapidKey(apiUrl?: string): Promise<{
|
|
8
|
+
publicKey: string;
|
|
9
|
+
}>;
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/types/TokenPair.d.ts
|
|
12
|
+
type TokenPair = {
|
|
13
|
+
accessToken: string;
|
|
14
|
+
refreshToken: string;
|
|
15
|
+
};
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/api/refreshHubTokens.d.ts
|
|
18
|
+
declare function refreshHubTokens(apiUrl: string, refreshToken: string): Promise<TokenPair>;
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/api/registerHub.d.ts
|
|
21
|
+
declare function registerHub(apiUrl: string): Promise<TokenPair>;
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/types/PushSubscriptionParams.d.ts
|
|
24
|
+
type PushSubscriptionParams = {
|
|
25
|
+
endpoint: string;
|
|
26
|
+
keys: {
|
|
27
|
+
p256dh: string;
|
|
28
|
+
auth: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/types/RevokeParams.d.ts
|
|
33
|
+
interface RevokeParams {
|
|
34
|
+
agentId: string;
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region src/ws/MessageRequest.d.ts
|
|
38
|
+
interface MessageRequest<TPayload> {
|
|
39
|
+
readonly messageId: string;
|
|
40
|
+
readonly agentId: string;
|
|
41
|
+
readonly method: string;
|
|
42
|
+
readonly payload: TPayload;
|
|
43
|
+
respond(status: string, payloadResponse?: unknown): void;
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/ws/TransactionRequest.d.ts
|
|
47
|
+
interface TransactionRequest extends MessageRequest<EthSendTransactionParams$1> {
|
|
48
|
+
approve(result: EthSendTransactionResult$1): void;
|
|
49
|
+
reject(reason?: string): void;
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region src/types/TransactionRequestHandler.d.ts
|
|
53
|
+
type TransactionRequestHandler = (request: TransactionRequest) => void | Promise<void>;
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/ws/ConnectionRequest.d.ts
|
|
56
|
+
interface ConnectionRequest {
|
|
57
|
+
readonly agentPairingCode: string;
|
|
58
|
+
readonly agent: Agent$1;
|
|
59
|
+
approve(): Promise<void>;
|
|
60
|
+
reject(): Promise<void>;
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/core/BananalinkHubConfig.d.ts
|
|
64
|
+
interface BananalinkHubConfig {
|
|
65
|
+
apiUrl?: string;
|
|
66
|
+
wsUrl?: string;
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/core/BananalinkHub.d.ts
|
|
70
|
+
declare class BananalinkHub {
|
|
71
|
+
private static readonly DEFAULT_API_URL;
|
|
72
|
+
private static readonly DEFAULT_WS_URL;
|
|
73
|
+
private static readonly BIND_RESPONSE_TIMEOUT_MILLIS;
|
|
74
|
+
private readonly apiUrl;
|
|
75
|
+
private readonly wsUrl;
|
|
76
|
+
private ws;
|
|
77
|
+
private accessToken;
|
|
78
|
+
private transactionHandler;
|
|
79
|
+
private unsubscribeMessages;
|
|
80
|
+
constructor(config?: BananalinkHubConfig);
|
|
81
|
+
connect(accessToken: string): Promise<void>;
|
|
82
|
+
disconnect(): void;
|
|
83
|
+
subscribePush(subscription: PushSubscriptionParams): void;
|
|
84
|
+
unsubscribePush(endpoint: string): void;
|
|
85
|
+
onTransactionRequest(handler: TransactionRequestHandler): () => void;
|
|
86
|
+
getConnectionRequest(params: ConnectionRequestParams$1): Promise<ConnectionRequest>;
|
|
87
|
+
revoke(params: RevokeParams): Promise<void>;
|
|
88
|
+
private listenForMessages;
|
|
89
|
+
private dispatchTransactionRequest;
|
|
90
|
+
private getTransportHandle;
|
|
91
|
+
private bind;
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/errors/BananalinkError.d.ts
|
|
95
|
+
declare class BananalinkError extends Error {
|
|
96
|
+
constructor(message: string, options?: ErrorOptions);
|
|
97
|
+
}
|
|
98
|
+
//#endregion
|
|
99
|
+
//#region src/errors/ApiError.d.ts
|
|
100
|
+
declare class ApiError extends BananalinkError {
|
|
101
|
+
readonly status: number;
|
|
102
|
+
readonly body: unknown;
|
|
103
|
+
constructor(status: number, body: unknown);
|
|
104
|
+
}
|
|
105
|
+
//#endregion
|
|
106
|
+
//#region src/errors/BindError.d.ts
|
|
107
|
+
declare class BindError extends BananalinkError {
|
|
108
|
+
readonly error: 'INVALID_JWT' | 'JWT_EXPIRED';
|
|
109
|
+
constructor(error: 'INVALID_JWT' | 'JWT_EXPIRED');
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
112
|
+
//#region src/errors/ConnectionError.d.ts
|
|
113
|
+
declare class ConnectionError extends BananalinkError {
|
|
114
|
+
constructor(message: string, options?: ErrorOptions);
|
|
115
|
+
}
|
|
116
|
+
//#endregion
|
|
117
|
+
//#region src/errors/NotConnectedError.d.ts
|
|
118
|
+
declare class NotConnectedError extends BananalinkError {
|
|
119
|
+
constructor();
|
|
120
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region src/types/BuildSiweMessageParams.d.ts
|
|
123
|
+
interface BuildSiweMessageParams {
|
|
124
|
+
domain: string;
|
|
125
|
+
address: string;
|
|
126
|
+
uri: string;
|
|
127
|
+
statement: string;
|
|
128
|
+
nonce: string;
|
|
129
|
+
chainId: number;
|
|
130
|
+
issuedAt?: string;
|
|
131
|
+
}
|
|
132
|
+
//#endregion
|
|
133
|
+
//#region src/types/Signer.d.ts
|
|
134
|
+
interface Signer {
|
|
135
|
+
address: string;
|
|
136
|
+
signMessage: (message: string) => Promise<string>;
|
|
137
|
+
}
|
|
138
|
+
//#endregion
|
|
139
|
+
//#region src/utils/buildSiweMessage.d.ts
|
|
140
|
+
declare function buildSiweMessage(params: BuildSiweMessageParams): string;
|
|
141
|
+
//#endregion
|
|
142
|
+
//#region src/utils/parseDeepLink.d.ts
|
|
143
|
+
declare function parseDeepLink(deepLink: string): DeepLinkParams$1;
|
|
144
|
+
//#endregion
|
|
145
|
+
export { type Agent, ApiError, BananalinkError, BananalinkHub, type BananalinkHubConfig, BindError, type BuildSiweMessageParams, ConnectionError, type ConnectionRequest, type ConnectionRequestParams, type DeepLinkParams, type EthSendTransactionParams, type EthSendTransactionResult, type MessageRequest, NotConnectedError, type PushSubscriptionParams, type RevokeParams, type Signer, type TokenPair, type TransactionRequest, type TransactionRequestHandler, buildSiweMessage, fetchAgent, fetchVapidKey, parseDeepLink, refreshHubTokens, registerHub };
|
|
146
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/api/fetchAgent.ts","../src/api/fetchVapidKey.ts","../src/types/TokenPair.ts","../src/api/refreshHubTokens.ts","../src/api/registerHub.ts","../src/types/PushSubscriptionParams.ts","../src/types/RevokeParams.ts","../src/ws/MessageRequest.ts","../src/ws/TransactionRequest.ts","../src/types/TransactionRequestHandler.ts","../src/ws/ConnectionRequest.ts","../src/core/BananalinkHubConfig.ts","../src/core/BananalinkHub.ts","../src/errors/BananalinkError.ts","../src/errors/ApiError.ts","../src/errors/BindError.ts","../src/errors/ConnectionError.ts","../src/errors/NotConnectedError.ts","../src/types/BuildSiweMessageParams.ts","../src/types/Signer.ts","../src/utils/buildSiweMessage.ts","../src/utils/parseDeepLink.ts"],"mappings":";;;iBAGsB,UAAA,CAAW,MAAA,UAAgB,gBAAA,WAA2B,OAAA,CAAQ,OAAA;;;iBCD9D,aAAA,CAAc,MAAA,YAAiD,OAAA;EAAU,SAAA;AAAA;;;KCFnF,SAAA;EACV,WAAA;EACA,YAAA;AAAA;;;iBCCoB,gBAAA,CAAiB,MAAA,UAAgB,YAAA,WAAuB,OAAA,CAAQ,SAAA;;;iBCAhE,WAAA,CAAY,MAAA,WAAiB,OAAA,CAAQ,SAAA;;;KCH/C,sBAAA;EAA2B,QAAA;EAAkB,IAAA;IAAQ,MAAA;IAAgB,IAAA;EAAA;AAAA;;;UCAhE,YAAA;EACf,OAAA;AAAA;;;UCDe,cAAA;EAAA,SACN,SAAA;EAAA,SACA,OAAA;EAAA,SACA,MAAA;EAAA,SACA,OAAA,EAAS,QAAA;EAClB,OAAA,CAAQ,MAAA,UAAgB,eAAA;AAAA;;;UCFT,kBAAA,SAA2B,cAAA,CAAe,0BAAA;EACzD,OAAA,CAAQ,MAAA,EAAQ,0BAAA;EAChB,MAAA,CAAO,MAAA;AAAA;;;KCHG,yBAAA,IAA6B,OAAA,EAAS,kBAAA,YAA8B,OAAA;;;UCA/D,iBAAA;EAAA,SACN,gBAAA;EAAA,SACA,KAAA,EAAO,OAAA;EAChB,OAAA,IAAW,OAAA;EACX,MAAA,IAAU,OAAA;AAAA;;;UCNK,mBAAA;EACf,MAAA;EACA,KAAA;AAAA;;;cCyBW,aAAA;EAAA,wBACa,eAAA;EAAA,wBACA,cAAA;EAAA,wBACA,4BAAA;EAAA,iBAEP,MAAA;EAAA,iBACA,KAAA;EAAA,QACT,EAAA;EAAA,QACA,WAAA;EAAA,QACA,kBAAA;EAAA,QACA,mBAAA;cAEI,MAAA,GAAS,mBAAA;EAKf,OAAA,CAAQ,WAAA,WAAsB,OAAA;EAgCpC,UAAA,CAAA;EAOA,aAAA,CAAc,YAAA,EAAc,sBAAA;EAyB5B,eAAA,CAAgB,QAAA;EAiBhB,oBAAA,CAAqB,OAAA,EAAS,yBAAA;EAQxB,oBAAA,CAAqB,MAAA,EAAQ,yBAAA,GAA0B,OAAA,CAAQ,iBAAA;EAkB/D,MAAA,CAAO,MAAA,EAAQ,YAAA,GAAe,OAAA;EAAA,QAW5B,iBAAA;EAAA,QAYA,0BAAA;EAAA,QAqBM,kBAAA;EAAA,QASA,IAAA;AAAA;;;cC5MH,eAAA,SAAwB,KAAA;cACvB,OAAA,UAAiB,OAAA,GAAU,YAAA;AAAA;;;cCC5B,QAAA,SAAiB,eAAA;EAAA,SACZ,MAAA;EAAA,SACA,IAAA;cAEJ,MAAA,UAAgB,IAAA;AAAA;;;cCJjB,SAAA,SAAkB,eAAA;EAAA,SACD,KAAA;cAAA,KAAA;AAAA;;;cCDjB,eAAA,SAAwB,eAAA;cACvB,OAAA,UAAiB,OAAA,GAAU,YAAA;AAAA;;;cCD5B,iBAAA,SAA0B,eAAA;EAAA,WAAA,CAAA;AAAA;;;UCFtB,sBAAA;EACf,MAAA;EACA,OAAA;EACA,GAAA;EACA,SAAA;EACA,KAAA;EACA,OAAA;EACA,QAAA;AAAA;;;UCPe,MAAA;EACf,OAAA;EACA,WAAA,GAAc,OAAA,aAAoB,OAAA;AAAA;;;iBCApB,gBAAA,CAAiB,MAAA,EAAQ,sBAAA;;;iBCCzB,aAAA,CAAc,QAAA,WAAmB,gBAAA"}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import { BindTransportError, MESSAGE_METHOD_SEND_TRANSACTION, bindTransport, connectWebSocket, createReconnectingTransport, isMessageRequestMessage } from "@bananalink-test/sdk-core";
|
|
2
|
+
|
|
3
|
+
//#region src/errors/BananalinkError.ts
|
|
4
|
+
var BananalinkError = class extends Error {
|
|
5
|
+
constructor(message, options) {
|
|
6
|
+
super(message, options);
|
|
7
|
+
this.name = "BananalinkError";
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/errors/ApiError.ts
|
|
13
|
+
var ApiError = class extends BananalinkError {
|
|
14
|
+
status;
|
|
15
|
+
body;
|
|
16
|
+
constructor(status, body) {
|
|
17
|
+
super(`API request failed with status ${status}`);
|
|
18
|
+
this.name = "ApiError";
|
|
19
|
+
this.status = status;
|
|
20
|
+
this.body = body;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/api/fetchAgent.ts
|
|
26
|
+
async function fetchAgent(apiUrl, agentPairingCode) {
|
|
27
|
+
const response = await fetch(`${apiUrl}/agents/${encodeURIComponent(agentPairingCode)}`);
|
|
28
|
+
if (!response.ok) {
|
|
29
|
+
const body = await response.json().catch(() => null);
|
|
30
|
+
throw new ApiError(response.status, body);
|
|
31
|
+
}
|
|
32
|
+
const body = await response.json();
|
|
33
|
+
if (!isAgent(body)) throw new ApiError(response.status, body);
|
|
34
|
+
return body;
|
|
35
|
+
}
|
|
36
|
+
function isAgent(value) {
|
|
37
|
+
if (typeof value !== "object" || value === null) return false;
|
|
38
|
+
const record = value;
|
|
39
|
+
return typeof record.agentId === "string" && typeof record.agentName === "string";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region src/api/fetchVapidKey.ts
|
|
44
|
+
async function fetchVapidKey(apiUrl = "https://api.dev.banana.link") {
|
|
45
|
+
const response = await fetch(`${apiUrl}/push/vapid-key`);
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
const body = await response.json().catch(() => null);
|
|
48
|
+
throw new ApiError(response.status, body);
|
|
49
|
+
}
|
|
50
|
+
const body = await response.json();
|
|
51
|
+
if (typeof body !== "object" || body === null || !("publicKey" in body)) throw new ApiError(response.status, body);
|
|
52
|
+
const { publicKey } = body;
|
|
53
|
+
if (typeof publicKey !== "string" || publicKey.length === 0) throw new ApiError(response.status, body);
|
|
54
|
+
return { publicKey };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region src/api/refreshHubTokens.ts
|
|
59
|
+
async function refreshHubTokens(apiUrl, refreshToken) {
|
|
60
|
+
const response = await fetch(`${apiUrl}/hubs/tokens/refresh`, {
|
|
61
|
+
method: "POST",
|
|
62
|
+
headers: { "Content-Type": "application/json" },
|
|
63
|
+
body: JSON.stringify({ refreshToken })
|
|
64
|
+
});
|
|
65
|
+
if (!response.ok) {
|
|
66
|
+
const responseBody = await response.json().catch(() => null);
|
|
67
|
+
throw new ApiError(response.status, responseBody);
|
|
68
|
+
}
|
|
69
|
+
const responseBody = await response.json().catch(() => null);
|
|
70
|
+
if (!isTokenPair$1(responseBody)) throw new ApiError(response.status, responseBody);
|
|
71
|
+
return responseBody;
|
|
72
|
+
}
|
|
73
|
+
function isTokenPair$1(value) {
|
|
74
|
+
if (typeof value !== "object" || value === null) return false;
|
|
75
|
+
return "accessToken" in value && typeof value.accessToken === "string" && "refreshToken" in value && typeof value.refreshToken === "string";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region src/api/registerHub.ts
|
|
80
|
+
async function registerHub(apiUrl) {
|
|
81
|
+
const response = await fetch(`${apiUrl}/hubs`, { method: "POST" });
|
|
82
|
+
if (!response.ok) {
|
|
83
|
+
const responseBody = await response.json().catch(() => null);
|
|
84
|
+
throw new ApiError(response.status, responseBody);
|
|
85
|
+
}
|
|
86
|
+
const responseBody = await response.json().catch(() => null);
|
|
87
|
+
if (!isTokenPair(responseBody)) throw new ApiError(response.status, responseBody);
|
|
88
|
+
return responseBody;
|
|
89
|
+
}
|
|
90
|
+
function isTokenPair(value) {
|
|
91
|
+
if (typeof value !== "object" || value === null) return false;
|
|
92
|
+
return "accessToken" in value && typeof value.accessToken === "string" && "refreshToken" in value && typeof value.refreshToken === "string";
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/api/deleteAgentTokens.ts
|
|
97
|
+
async function deleteAgentTokens(apiUrl, agentId, accessToken) {
|
|
98
|
+
const response = await fetch(`${apiUrl}/hubs/agents/${encodeURIComponent(agentId)}/tokens`, {
|
|
99
|
+
method: "DELETE",
|
|
100
|
+
headers: {
|
|
101
|
+
"Content-Type": "application/json",
|
|
102
|
+
Authorization: `Bearer ${accessToken}`
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
if (!response.ok) {
|
|
106
|
+
const responseBody = await response.json().catch(() => null);
|
|
107
|
+
throw new ApiError(response.status, responseBody);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
//#endregion
|
|
112
|
+
//#region src/errors/BindError.ts
|
|
113
|
+
var BindError = class extends BananalinkError {
|
|
114
|
+
constructor(error) {
|
|
115
|
+
super(`Hub bind failed with error: ${error}`);
|
|
116
|
+
this.error = error;
|
|
117
|
+
this.name = "BindError";
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region src/errors/ConnectionError.ts
|
|
123
|
+
var ConnectionError = class extends BananalinkError {
|
|
124
|
+
constructor(message, options) {
|
|
125
|
+
super(message, options);
|
|
126
|
+
this.name = "ConnectionError";
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
//#endregion
|
|
131
|
+
//#region src/errors/NotConnectedError.ts
|
|
132
|
+
var NotConnectedError = class extends BananalinkError {
|
|
133
|
+
constructor() {
|
|
134
|
+
super("Hub is not connected. Call connect() first.");
|
|
135
|
+
this.name = "NotConnectedError";
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region src/ws/createConnectionRequest.ts
|
|
141
|
+
function createConnectionRequest(params) {
|
|
142
|
+
return {
|
|
143
|
+
agentPairingCode: params.agentPairingCode,
|
|
144
|
+
agent: params.agent,
|
|
145
|
+
async approve() {
|
|
146
|
+
const authorizeMessage = {
|
|
147
|
+
type: "authorize",
|
|
148
|
+
code: params.agentPairingCode
|
|
149
|
+
};
|
|
150
|
+
params.ws.send(authorizeMessage);
|
|
151
|
+
},
|
|
152
|
+
async reject() {
|
|
153
|
+
const rejectMessage = {
|
|
154
|
+
type: "reject",
|
|
155
|
+
code: params.agentPairingCode
|
|
156
|
+
};
|
|
157
|
+
params.ws.send(rejectMessage);
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
//#endregion
|
|
163
|
+
//#region src/ws/createMessageRequest.ts
|
|
164
|
+
function createMessageRequest(message, ws) {
|
|
165
|
+
return {
|
|
166
|
+
messageId: message.messageId,
|
|
167
|
+
agentId: message.agentId,
|
|
168
|
+
method: message.method,
|
|
169
|
+
payload: message.payload,
|
|
170
|
+
respond(status, payloadResponse) {
|
|
171
|
+
const response = {
|
|
172
|
+
type: "message_response",
|
|
173
|
+
msgId: message.messageId,
|
|
174
|
+
status,
|
|
175
|
+
payloadResponse
|
|
176
|
+
};
|
|
177
|
+
ws.send(response);
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
//#endregion
|
|
183
|
+
//#region src/ws/createTransactionRequest.ts
|
|
184
|
+
function createTransactionRequest(message, ws) {
|
|
185
|
+
const base = createMessageRequest(message, ws);
|
|
186
|
+
return {
|
|
187
|
+
...base,
|
|
188
|
+
payload: base.payload[0],
|
|
189
|
+
approve(result) {
|
|
190
|
+
base.respond("approved", result);
|
|
191
|
+
},
|
|
192
|
+
reject(reason) {
|
|
193
|
+
base.respond("rejected", reason);
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
//#endregion
|
|
199
|
+
//#region src/core/BananalinkHub.ts
|
|
200
|
+
var BananalinkHub = class BananalinkHub {
|
|
201
|
+
static DEFAULT_API_URL = "https://api.dev.banana.link";
|
|
202
|
+
static DEFAULT_WS_URL = "wss://ws.dev.banana.link";
|
|
203
|
+
static BIND_RESPONSE_TIMEOUT_MILLIS = 20 * 1e3;
|
|
204
|
+
apiUrl;
|
|
205
|
+
wsUrl;
|
|
206
|
+
ws = null;
|
|
207
|
+
accessToken = null;
|
|
208
|
+
transactionHandler = null;
|
|
209
|
+
unsubscribeMessages = null;
|
|
210
|
+
constructor(config) {
|
|
211
|
+
this.apiUrl = stripTrailingSlash(config?.apiUrl ?? BananalinkHub.DEFAULT_API_URL);
|
|
212
|
+
this.wsUrl = stripTrailingSlash(config?.wsUrl ?? BananalinkHub.DEFAULT_WS_URL);
|
|
213
|
+
}
|
|
214
|
+
async connect(accessToken) {
|
|
215
|
+
if (!accessToken.trim()) throw new BananalinkError("accessToken is required");
|
|
216
|
+
this.disconnect();
|
|
217
|
+
let transportHandle;
|
|
218
|
+
try {
|
|
219
|
+
transportHandle = await this.getTransportHandle();
|
|
220
|
+
} catch (error) {
|
|
221
|
+
throw new ConnectionError("Unable to establish hub websocket connection", { cause: error });
|
|
222
|
+
}
|
|
223
|
+
try {
|
|
224
|
+
await this.bind(transportHandle, accessToken);
|
|
225
|
+
this.accessToken = accessToken;
|
|
226
|
+
this.ws = createReconnectingTransport(transportHandle, {
|
|
227
|
+
reconnectTransport: async () => this.getTransportHandle(),
|
|
228
|
+
onReconnect: async (th) => this.bind(th, accessToken),
|
|
229
|
+
maxReconnectAttempts: 5,
|
|
230
|
+
baseDelayReconnectMs: 1e3
|
|
231
|
+
});
|
|
232
|
+
} catch (error) {
|
|
233
|
+
transportHandle.close();
|
|
234
|
+
throw error;
|
|
235
|
+
}
|
|
236
|
+
this.listenForMessages(this.ws);
|
|
237
|
+
}
|
|
238
|
+
disconnect() {
|
|
239
|
+
this.unsubscribeMessages?.();
|
|
240
|
+
this.unsubscribeMessages = null;
|
|
241
|
+
this.ws?.close();
|
|
242
|
+
this.ws = null;
|
|
243
|
+
}
|
|
244
|
+
subscribePush(subscription) {
|
|
245
|
+
if (!this.ws) throw new NotConnectedError();
|
|
246
|
+
if (!subscription.endpoint.trim()) throw new BananalinkError("subscription endpoint is required");
|
|
247
|
+
if (!subscription.keys.auth.trim()) throw new BananalinkError("subscription keys.auth is required");
|
|
248
|
+
if (!subscription.keys.p256dh.trim()) throw new BananalinkError("subscription keys.p256dh is required");
|
|
249
|
+
const message = {
|
|
250
|
+
type: "subscribe_push",
|
|
251
|
+
subscription
|
|
252
|
+
};
|
|
253
|
+
this.ws.send(message);
|
|
254
|
+
}
|
|
255
|
+
unsubscribePush(endpoint) {
|
|
256
|
+
if (!this.ws) throw new NotConnectedError();
|
|
257
|
+
if (!endpoint.trim()) throw new BananalinkError("subscription endpoint is required");
|
|
258
|
+
const message = {
|
|
259
|
+
type: "unsubscribe_push",
|
|
260
|
+
endpoint
|
|
261
|
+
};
|
|
262
|
+
this.ws.send(message);
|
|
263
|
+
}
|
|
264
|
+
onTransactionRequest(handler) {
|
|
265
|
+
this.transactionHandler = handler;
|
|
266
|
+
return () => {
|
|
267
|
+
this.transactionHandler = null;
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
async getConnectionRequest(params) {
|
|
271
|
+
if (!this.ws) throw new NotConnectedError();
|
|
272
|
+
if (!params.agentPairingCode.trim()) throw new BananalinkError("agentPairingCode is required");
|
|
273
|
+
const agent = await fetchAgent(this.apiUrl, params.agentPairingCode);
|
|
274
|
+
return createConnectionRequest({
|
|
275
|
+
agentPairingCode: params.agentPairingCode,
|
|
276
|
+
agent,
|
|
277
|
+
ws: this.ws
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
async revoke(params) {
|
|
281
|
+
if (!params.agentId.trim()) throw new BananalinkError("agentId is required");
|
|
282
|
+
if (!this.accessToken) throw new BananalinkError("accessToken is required");
|
|
283
|
+
await deleteAgentTokens(this.apiUrl, params.agentId, this.accessToken);
|
|
284
|
+
}
|
|
285
|
+
listenForMessages(ws) {
|
|
286
|
+
this.unsubscribeMessages = ws.onMessage((payload) => {
|
|
287
|
+
if (!isMessageRequestMessage(payload)) return;
|
|
288
|
+
if (payload.method === MESSAGE_METHOD_SEND_TRANSACTION && this.transactionHandler) this.dispatchTransactionRequest(this.transactionHandler, payload, ws);
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
dispatchTransactionRequest(handler, payload, ws) {
|
|
292
|
+
const request = createTransactionRequest(payload, ws);
|
|
293
|
+
const safeReject = (error) => {
|
|
294
|
+
try {
|
|
295
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
296
|
+
request.reject(`transaction handler failed: ${message}`);
|
|
297
|
+
} catch {}
|
|
298
|
+
};
|
|
299
|
+
try {
|
|
300
|
+
Promise.resolve(handler(request)).catch(safeReject);
|
|
301
|
+
} catch (error) {
|
|
302
|
+
safeReject(error);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
async getTransportHandle() {
|
|
306
|
+
return await connectWebSocket({
|
|
307
|
+
url: this.wsUrl,
|
|
308
|
+
pingIntervalMs: 3e4,
|
|
309
|
+
pongTimeoutMs: 5e3,
|
|
310
|
+
maxReconnectAttempts: 0
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
async bind(ws, accessToken) {
|
|
314
|
+
try {
|
|
315
|
+
await bindTransport(ws, accessToken, {
|
|
316
|
+
timeoutMs: BananalinkHub.BIND_RESPONSE_TIMEOUT_MILLIS,
|
|
317
|
+
createClosedError: () => new ConnectionError("Connection closed unexpectedly while waiting for hub bind response"),
|
|
318
|
+
createTimeoutError: () => new ConnectionError("Timed out waiting for hub bind response")
|
|
319
|
+
});
|
|
320
|
+
} catch (error) {
|
|
321
|
+
if (error instanceof BindTransportError) throw new BindError(error.code);
|
|
322
|
+
throw error;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
function stripTrailingSlash(url) {
|
|
327
|
+
return url.replace(/\/+$/, "");
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
//#endregion
|
|
331
|
+
//#region src/utils/buildSiweMessage.ts
|
|
332
|
+
function buildSiweMessage(params) {
|
|
333
|
+
const issuedAt = params.issuedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
334
|
+
return `${params.domain} wants you to sign in with your Ethereum account:\n${params.address}\n\n${params.statement}\n\nURI: ${params.uri}\nVersion: 1\nChain ID: ${params.chainId}\nNonce: ${params.nonce}\nIssued At: ${issuedAt}`;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
//#endregion
|
|
338
|
+
//#region src/utils/parseDeepLink.ts
|
|
339
|
+
function parseDeepLink(deepLink) {
|
|
340
|
+
let url;
|
|
341
|
+
try {
|
|
342
|
+
url = new URL(deepLink);
|
|
343
|
+
} catch (error) {
|
|
344
|
+
throw new BananalinkError("Invalid deep link URL", { cause: error });
|
|
345
|
+
}
|
|
346
|
+
const code = url.searchParams.get("code");
|
|
347
|
+
if (!code) throw new BananalinkError("Invalid deep link: missing agent pairing code");
|
|
348
|
+
return { code };
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
//#endregion
|
|
352
|
+
export { ApiError, BananalinkError, BananalinkHub, BindError, ConnectionError, NotConnectedError, buildSiweMessage, fetchAgent, fetchVapidKey, parseDeepLink, refreshHubTokens, registerHub };
|
|
353
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["isTokenPair"],"sources":["../src/errors/BananalinkError.ts","../src/errors/ApiError.ts","../src/api/fetchAgent.ts","../src/api/fetchVapidKey.ts","../src/api/refreshHubTokens.ts","../src/api/registerHub.ts","../src/api/deleteAgentTokens.ts","../src/errors/BindError.ts","../src/errors/ConnectionError.ts","../src/errors/NotConnectedError.ts","../src/ws/createConnectionRequest.ts","../src/ws/createMessageRequest.ts","../src/ws/createTransactionRequest.ts","../src/core/BananalinkHub.ts","../src/utils/buildSiweMessage.ts","../src/utils/parseDeepLink.ts"],"sourcesContent":["export class BananalinkError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'BananalinkError';\n }\n}\n","import { BananalinkError } from './BananalinkError.js';\n\nexport class ApiError extends BananalinkError {\n public readonly status: number;\n public readonly body: unknown;\n\n constructor(status: number, body: unknown) {\n super(`API request failed with status ${status}`);\n this.name = 'ApiError';\n this.status = status;\n this.body = body;\n }\n}\n","import type { Agent } from '@bananalink-test/sdk-core';\nimport { ApiError } from '../errors/ApiError.js';\n\nexport async function fetchAgent(apiUrl: string, agentPairingCode: string): Promise<Agent> {\n const response = await fetch(`${apiUrl}/agents/${encodeURIComponent(agentPairingCode)}`);\n\n if (!response.ok) {\n const body = await response.json().catch(() => null);\n throw new ApiError(response.status, body);\n }\n\n const body = await response.json();\n\n if (!isAgent(body)) {\n throw new ApiError(response.status, body);\n }\n\n return body;\n}\n\nfunction isAgent(value: unknown): value is Agent {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n\n const record = value as Record<string, unknown>;\n\n return typeof record.agentId === 'string' && typeof record.agentName === 'string';\n}\n","import { ApiError } from '../errors/ApiError.js';\n\nexport async function fetchVapidKey(apiUrl: string = 'https://api.dev.banana.link'): Promise<{ publicKey: string }> {\n const response = await fetch(`${apiUrl}/push/vapid-key`);\n\n if (!response.ok) {\n const body = await response.json().catch(() => null);\n throw new ApiError(response.status, body);\n }\n\n const body: unknown = await response.json();\n\n if (typeof body !== 'object' || body === null || !('publicKey' in body)) {\n throw new ApiError(response.status, body);\n }\n\n const { publicKey } = body as { publicKey: unknown };\n\n if (typeof publicKey !== 'string' || publicKey.length === 0) {\n throw new ApiError(response.status, body);\n }\n\n return { publicKey };\n}\n","import { ApiError } from '../errors/ApiError.js';\nimport type { TokenPair } from '../types/TokenPair.js';\n\nexport async function refreshHubTokens(apiUrl: string, refreshToken: string): Promise<TokenPair> {\n const response = await fetch(`${apiUrl}/hubs/tokens/refresh`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ refreshToken }),\n });\n\n if (!response.ok) {\n const responseBody = await response.json().catch(() => null);\n throw new ApiError(response.status, responseBody);\n }\n\n const responseBody: unknown = await response.json().catch(() => null);\n if (!isTokenPair(responseBody)) {\n throw new ApiError(response.status, responseBody);\n }\n\n return responseBody;\n}\n\nfunction isTokenPair(value: unknown): value is TokenPair {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n\n return (\n 'accessToken' in value &&\n typeof value.accessToken === 'string' &&\n 'refreshToken' in value &&\n typeof value.refreshToken === 'string'\n );\n}\n","import { ApiError } from '../errors/ApiError.js';\nimport type { TokenPair } from '../types/TokenPair.js';\n\nexport async function registerHub(apiUrl: string): Promise<TokenPair> {\n const response = await fetch(`${apiUrl}/hubs`, { method: 'POST' });\n\n if (!response.ok) {\n const responseBody = await response.json().catch(() => null);\n throw new ApiError(response.status, responseBody);\n }\n\n const responseBody: unknown = await response.json().catch(() => null);\n if (!isTokenPair(responseBody)) {\n throw new ApiError(response.status, responseBody);\n }\n\n return responseBody;\n}\n\nfunction isTokenPair(value: unknown): value is TokenPair {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n\n return (\n 'accessToken' in value &&\n typeof value.accessToken === 'string' &&\n 'refreshToken' in value &&\n typeof value.refreshToken === 'string'\n );\n}\n","import { ApiError } from '../errors/ApiError.js';\n\nexport async function deleteAgentTokens(apiUrl: string, agentId: string, accessToken: string): Promise<void> {\n const response = await fetch(`${apiUrl}/hubs/agents/${encodeURIComponent(agentId)}/tokens`, {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${accessToken}` },\n });\n\n if (!response.ok) {\n const responseBody = await response.json().catch(() => null);\n throw new ApiError(response.status, responseBody);\n }\n}\n","import { BananalinkError } from './BananalinkError.js';\n\nexport class BindError extends BananalinkError {\n constructor(public readonly error: 'INVALID_JWT' | 'JWT_EXPIRED') {\n super(`Hub bind failed with error: ${error}`);\n this.name = 'BindError';\n }\n}\n","import { BananalinkError } from './BananalinkError.js';\n\nexport class ConnectionError extends BananalinkError {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'ConnectionError';\n }\n}\n","import { BananalinkError } from './BananalinkError.js';\n\nexport class NotConnectedError extends BananalinkError {\n constructor() {\n super('Hub is not connected. Call connect() first.');\n this.name = 'NotConnectedError';\n }\n}\n","import type { Agent, AuthorizeMessage, RejectMessage, TransportHandle } from '@bananalink-test/sdk-core';\nimport type { ConnectionRequest } from './ConnectionRequest.js';\n\nexport function createConnectionRequest(params: {\n agentPairingCode: string;\n agent: Agent;\n ws: TransportHandle;\n}): ConnectionRequest {\n return {\n agentPairingCode: params.agentPairingCode,\n agent: params.agent,\n\n async approve(): Promise<void> {\n const authorizeMessage: AuthorizeMessage = {\n type: 'authorize',\n code: params.agentPairingCode,\n };\n\n params.ws.send(authorizeMessage);\n },\n\n async reject(): Promise<void> {\n const rejectMessage: RejectMessage = {\n type: 'reject',\n code: params.agentPairingCode,\n };\n\n params.ws.send(rejectMessage);\n },\n };\n}\n","import type { MessageRequestMessage, MessageResponseMessage, TransportHandle } from '@bananalink-test/sdk-core';\nimport type { MessageRequest } from './MessageRequest.js';\n\nexport function createMessageRequest<TPayload>(\n message: MessageRequestMessage,\n ws: TransportHandle,\n): MessageRequest<TPayload> {\n return {\n messageId: message.messageId,\n agentId: message.agentId,\n method: message.method,\n payload: message.payload as TPayload,\n\n respond(status: string, payloadResponse?: unknown): void {\n const response: MessageResponseMessage = {\n type: 'message_response',\n msgId: message.messageId,\n status,\n payloadResponse,\n };\n\n ws.send(response);\n },\n };\n}\n","import type {\n EthSendTransactionParams,\n EthSendTransactionResult,\n MessageRequestMessage,\n TransportHandle,\n} from '@bananalink-test/sdk-core';\nimport { createMessageRequest } from './createMessageRequest.js';\nimport type { TransactionRequest } from './TransactionRequest.js';\n\nexport function createTransactionRequest(message: MessageRequestMessage, ws: TransportHandle): TransactionRequest {\n const base = createMessageRequest<EthSendTransactionParams[]>(message, ws);\n\n return {\n ...base,\n payload: base.payload[0],\n\n approve(result: EthSendTransactionResult): void {\n base.respond('approved', result);\n },\n\n reject(reason?: string): void {\n base.respond('rejected', reason);\n },\n };\n}\n","import {\n BindTransportError,\n bindTransport,\n type ConnectionRequestParams,\n connectWebSocket,\n createReconnectingTransport,\n isMessageRequestMessage,\n MESSAGE_METHOD_SEND_TRANSACTION,\n type MessageRequestMessage,\n type SubscribePushMessage,\n type TransportHandle,\n type UnsubscribePushMessage,\n} from '@bananalink-test/sdk-core';\nimport { deleteAgentTokens } from '../api/deleteAgentTokens.js';\nimport { fetchAgent } from '../api/fetchAgent.js';\nimport { BananalinkError } from '../errors/BananalinkError.js';\nimport { BindError } from '../errors/BindError.js';\nimport { ConnectionError } from '../errors/ConnectionError.js';\nimport { NotConnectedError } from '../errors/NotConnectedError.js';\nimport type { PushSubscriptionParams } from '../types/PushSubscriptionParams.js';\nimport type { RevokeParams } from '../types/RevokeParams.js';\nimport type { TransactionRequestHandler } from '../types/TransactionRequestHandler.js';\nimport type { ConnectionRequest } from '../ws/ConnectionRequest.js';\nimport { createConnectionRequest } from '../ws/createConnectionRequest.js';\nimport { createTransactionRequest } from '../ws/createTransactionRequest.js';\nimport type { BananalinkHubConfig } from './BananalinkHubConfig.js';\n\nexport class BananalinkHub {\n private static readonly DEFAULT_API_URL = 'https://api.dev.banana.link';\n private static readonly DEFAULT_WS_URL = 'wss://ws.dev.banana.link';\n private static readonly BIND_RESPONSE_TIMEOUT_MILLIS = 20 * 1000;\n\n private readonly apiUrl: string;\n private readonly wsUrl: string;\n private ws: TransportHandle | null = null;\n private accessToken: string | null = null;\n private transactionHandler: TransactionRequestHandler | null = null;\n private unsubscribeMessages: (() => void) | null = null;\n\n constructor(config?: BananalinkHubConfig) {\n this.apiUrl = stripTrailingSlash(config?.apiUrl ?? BananalinkHub.DEFAULT_API_URL);\n this.wsUrl = stripTrailingSlash(config?.wsUrl ?? BananalinkHub.DEFAULT_WS_URL);\n }\n\n async connect(accessToken: string): Promise<void> {\n if (!accessToken.trim()) {\n throw new BananalinkError('accessToken is required');\n }\n\n this.disconnect();\n\n let transportHandle: TransportHandle;\n try {\n transportHandle = await this.getTransportHandle();\n } catch (error) {\n throw new ConnectionError('Unable to establish hub websocket connection', { cause: error });\n }\n\n try {\n await this.bind(transportHandle, accessToken);\n this.accessToken = accessToken;\n\n this.ws = createReconnectingTransport(transportHandle, {\n reconnectTransport: async () => this.getTransportHandle(),\n onReconnect: async (th) => this.bind(th, accessToken),\n maxReconnectAttempts: 5,\n baseDelayReconnectMs: 1000,\n });\n } catch (error) {\n transportHandle.close();\n throw error;\n }\n\n this.listenForMessages(this.ws);\n }\n\n disconnect(): void {\n this.unsubscribeMessages?.();\n this.unsubscribeMessages = null;\n this.ws?.close();\n this.ws = null;\n }\n\n subscribePush(subscription: PushSubscriptionParams) {\n if (!this.ws) {\n throw new NotConnectedError();\n }\n\n if (!subscription.endpoint.trim()) {\n throw new BananalinkError('subscription endpoint is required');\n }\n\n if (!subscription.keys.auth.trim()) {\n throw new BananalinkError('subscription keys.auth is required');\n }\n\n if (!subscription.keys.p256dh.trim()) {\n throw new BananalinkError('subscription keys.p256dh is required');\n }\n\n const message: SubscribePushMessage = {\n type: 'subscribe_push',\n subscription,\n };\n\n this.ws.send(message);\n }\n\n unsubscribePush(endpoint: string) {\n if (!this.ws) {\n throw new NotConnectedError();\n }\n\n if (!endpoint.trim()) {\n throw new BananalinkError('subscription endpoint is required');\n }\n\n const message: UnsubscribePushMessage = {\n type: 'unsubscribe_push',\n endpoint,\n };\n\n this.ws.send(message);\n }\n\n onTransactionRequest(handler: TransactionRequestHandler): () => void {\n this.transactionHandler = handler;\n\n return () => {\n this.transactionHandler = null;\n };\n }\n\n async getConnectionRequest(params: ConnectionRequestParams): Promise<ConnectionRequest> {\n if (!this.ws) {\n throw new NotConnectedError();\n }\n\n if (!params.agentPairingCode.trim()) {\n throw new BananalinkError('agentPairingCode is required');\n }\n\n const agent = await fetchAgent(this.apiUrl, params.agentPairingCode);\n\n return createConnectionRequest({\n agentPairingCode: params.agentPairingCode,\n agent,\n ws: this.ws,\n });\n }\n\n async revoke(params: RevokeParams): Promise<void> {\n if (!params.agentId.trim()) {\n throw new BananalinkError('agentId is required');\n }\n if (!this.accessToken) {\n throw new BananalinkError('accessToken is required');\n }\n\n await deleteAgentTokens(this.apiUrl, params.agentId, this.accessToken);\n }\n\n private listenForMessages(ws: TransportHandle): void {\n this.unsubscribeMessages = ws.onMessage((payload) => {\n if (!isMessageRequestMessage(payload)) {\n return;\n }\n\n if (payload.method === MESSAGE_METHOD_SEND_TRANSACTION && this.transactionHandler) {\n this.dispatchTransactionRequest(this.transactionHandler, payload, ws);\n }\n });\n }\n\n private dispatchTransactionRequest(\n handler: TransactionRequestHandler,\n payload: MessageRequestMessage,\n ws: TransportHandle,\n ): void {\n const request = createTransactionRequest(payload, ws);\n\n const safeReject = (error: unknown): void => {\n try {\n const message = error instanceof Error ? error.message : String(error);\n request.reject(`transaction handler failed: ${message}`);\n } catch {}\n };\n\n try {\n void Promise.resolve(handler(request)).catch(safeReject);\n } catch (error: unknown) {\n safeReject(error);\n }\n }\n\n private async getTransportHandle(): Promise<TransportHandle> {\n return await connectWebSocket({\n url: this.wsUrl,\n pingIntervalMs: 30_000,\n pongTimeoutMs: 5_000,\n maxReconnectAttempts: 0,\n });\n }\n\n private async bind(ws: TransportHandle, accessToken: string): Promise<void> {\n try {\n await bindTransport(ws, accessToken, {\n timeoutMs: BananalinkHub.BIND_RESPONSE_TIMEOUT_MILLIS,\n createClosedError: () =>\n new ConnectionError('Connection closed unexpectedly while waiting for hub bind response'),\n createTimeoutError: () => new ConnectionError('Timed out waiting for hub bind response'),\n });\n } catch (error) {\n if (error instanceof BindTransportError) {\n throw new BindError(error.code);\n }\n throw error;\n }\n }\n}\n\nfunction stripTrailingSlash(url: string): string {\n return url.replace(/\\/+$/, '');\n}\n","import type { BuildSiweMessageParams } from '../types/BuildSiweMessageParams.js';\n\nexport function buildSiweMessage(params: BuildSiweMessageParams): string {\n const issuedAt = params.issuedAt ?? new Date().toISOString();\n\n return (\n `${params.domain} wants you to sign in with your Ethereum account:\\n` +\n `${params.address}\\n` +\n `\\n` +\n `${params.statement}\\n` +\n `\\n` +\n `URI: ${params.uri}\\n` +\n `Version: 1\\n` +\n `Chain ID: ${params.chainId}\\n` +\n `Nonce: ${params.nonce}\\n` +\n `Issued At: ${issuedAt}`\n );\n}\n","import type { DeepLinkParams } from '@bananalink-test/sdk-core';\nimport { BananalinkError } from '../errors/BananalinkError.js';\n\nexport function parseDeepLink(deepLink: string): DeepLinkParams {\n let url: URL;\n\n try {\n url = new URL(deepLink);\n } catch (error) {\n throw new BananalinkError('Invalid deep link URL', { cause: error });\n }\n\n const code = url.searchParams.get('code');\n\n if (!code) {\n throw new BananalinkError('Invalid deep link: missing agent pairing code');\n }\n\n return { code };\n}\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bananalink-test/hub",
|
|
3
|
+
"version": "1.1.1",
|
|
4
|
+
"description": "",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": {
|
|
10
|
+
"types": "./dist/index.d.mts",
|
|
11
|
+
"default": "./dist/index.mjs"
|
|
12
|
+
},
|
|
13
|
+
"require": {
|
|
14
|
+
"types": "./dist/index.d.cts",
|
|
15
|
+
"default": "./dist/index.cjs"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"main": "./dist/index.cjs",
|
|
20
|
+
"module": "./dist/index.mjs",
|
|
21
|
+
"types": "./dist/index.d.mts",
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@biomejs/biome": "2.3.15",
|
|
30
|
+
"tsdown": "^0.20.3",
|
|
31
|
+
"typescript": "^5.9.3",
|
|
32
|
+
"vitest": "^4.0.18"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@bananalink-test/sdk-core": "0.8.1"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsdown",
|
|
39
|
+
"type-check": "tsc --noEmit",
|
|
40
|
+
"lint": "biome check .",
|
|
41
|
+
"dev": "tsdown --watch",
|
|
42
|
+
"test": "vitest run"
|
|
43
|
+
}
|
|
44
|
+
}
|